home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
security
/
log_tcp_5.1.shar
< prev
next >
Wrap
Internet Message Format
|
1993-03-24
|
151KB
From wietse@wzv.win.tue.nl Wed Mar 24 23:37:23 1993
Received: from svin01.win.tue.nl by svbs01.bs.win.tue.nl (4.1/1.45)
id AA16728; Wed, 24 Mar 93 23:37:23 +0100
Received: from svin09.info.win.tue.nl by svin01.win.tue.nl (4.1/1.45)
id AA00471; Wed, 24 Mar 93 23:37:18 +0100
Received: from wzv.win.tue.nl by svin09.info.win.tue.nl (4.1/1.45)
id AA02366; Wed, 24 Mar 93 23:33:04 +0100
Received: by wzv.win.tue.nl (4.1/1.45)
id AA01314; Wed, 24 Mar 93 23:06:25 +0100
Date: Wed, 24 Mar 93 23:06:25 +0100
From: wietse@wzv.win.tue.nl (Wietse Venema)
Message-Id: <9303242206.AA01314@wzv.win.tue.nl>
To: ecd@cert.org
Subject: tcp wrapper reveals SunOS 4.x kernel bug
Cc: wswietse@win.tue.nl
Status: OR
The new wrapper release causes occasional kernel panics with SunOS 4.x.
There is a bug in the getsockopt() system call implementation.
Getsockopt() was used to detect source-routing attacks. That code was
enabled by default. I have changed this: by default the code no longer
tries to expose source-routing attacks.
The result of this effort is below. Changes were made only to the
documentation, to the Makefile, and to the patchlevel.h file.
Please replace the wrapper archives on cert.org. I will post a separate
message to the cert-tools mailing list.
Wietse
--------------
With the programs that come with this kit you can monitor incoming
requests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
FINGER, SYSTAT, and many others.
Optional features are: access control based on pattern matching; remote
username lookup using the RFC 931 protocol; protection against attacks
from hosts that pretend to have someone elses name; protection against
attacks from hosts that pretend to have someone elses network address.
The programs can be installed without requiring any changes to existing
software or configuration files. By default, they just log the remote
host name and do some sanity checks on the origin the request. No
information is exchanged with the remote client process.
The most notable differences with respect to the previous release are:
- Optional protection against attacks from hosts that pretend to
have someone elses network address. For example, the address of a
trusted host within your own network.
- The access control language has been extended with a simple but
powerful operator that greatly simplifies the design of rule sets
(ALL: .foo.edu EXCEPT dialup.foo.edu). Blank lines are permitted,
and long lines can be continued with backslash-newline.
- All configurable stuff, including path names, has been moved into
the Makefile so that you no longer have to hack source code to just
configure the programs.
- Ported to Solaris 2. TLI-based applications not yet supported.
Several workarounds for System V bugs.
- A small loophole in the netgroup lookup code was closed, and the
remote username lookup code was made more portable.
- Still more documentation. The README file now provides tutorial
sections with introductions to client, server, inetd and syslogd.
The default mode of operation should be backwards compatible with
earlier versions.
Wietse Venema (wietse@wzv.win.tue.nl),
Department of Mathematics and Computing Science,
Eindhoven University of Technology,
The Netherlands.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: README miscd.c tcpd.c fromhost.c hosts_access.c
# shell_cmd.c log_tcp.h try.c refuse.c Makefile.dist hosts_access.5
# strcasecmp.c BLURB rfc931.c tcpd.8 hosts_info.c hosts_access.3
# hosts_ctl.c percent_x.c options.c clean_exit.c setenv.c
# patchlevel.h strtok.c fix_options.c inet_addr_fix
# Wrapped by wietse@wzv on Wed Mar 24 22:44:58 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(34888 characters\)
sed "s/^X//" >README <<'END_OF_README'
X@(#) README 1.10 93/03/24 22:42:46
X
X
XTable of contents
X-----------------
X
X 1 - Introduction
X 2 - Disclaimer
X 3 - Tutorials
X 3.1 - How it works
X 3.2 - Where the logging information goes
X 4 - Features
X 4.1 - Access control
X 4.2 - Host name spoofing
X 4.3 - Host address spoofing
X 4.4 - Remote username lookups
X 4.5 - Language extension hooks
X 5 - Other works
X 5.1 - Related documents
X 5.2 - Related software
X 6 - Limitations
X 6.1 - Known wrapper limitations
X 6.2 - Known system software bugs
X 7 - Configuration and installation
X 7.1 - Easy configuration and installation
X 7.2 - Advanced configuration and installation
X 7.3 - Daemons with arbitrary path names
X 7.4 - Building and testing the access control rules
X 7.5 - Other applications
X 8 - Acknowledgements
X
X1 - Introduction
X----------------
X
XWith this package you can monitor incoming connections to the SYSTAT,
XFINGER, FTP, TELNET, RLOGIN, RSH, EXEC, TFTP, TALK, and other network
Xservices.
X
XThe package provides tiny daemon wrapper programs that can be installed
Xwithout any changes to existing software or to existing configuration
Xfiles. The wrappers report the name of the remote host and of the
Xrequested service; the wrappers do not exchange information with the
Xremote client process, and impose no overhead on the actual
Xcommunication between the client and server applications.
X
XOptional features are: access control to restrict what systems can
Xconnect to your network daemons; remote user name lookups with the RFC
X931 protocol; additional protection against hosts that pretend to have
Xsomeone elses host name; additional protection against hosts that
Xpretend to have someone elses host address.
X
XEarly versions of the programs were tested with Ultrix >= 2.2, with
XSunOS >= 3.4 and ISC 2.2. Later versions have been installed on a wide
Xvariety of platforms such as SunOS 4.x and 5.x, Ultrix 3.x and 4.x, DEC
XOSF/1 T1.2-2, HP-UX 8.x, AIX 3.1.5, Apollo SR10.3.5, Sony, NeXT, SCO
XUNIX, DG/UX, Cray, and an unknown number of other ones.
X
XRequirements are that the network daemons are spawned by a super server
Xsuch as the inetd; a 4.3BSD-style socket programming interface; and the
Xavailability of a syslog(3) library and of a syslogd(8) daemon. The
Xwrappers should run without modification on any system that satisfies
Xthese requirements. Workarounds have been implemented for several
Xcommon bugs in systems software.
X
XWhat to do if this is your first encounter with the wrapper programs:
X1) read the tutorial sections for an introduction to the relevant
Xconcepts and terminology; 2) glance over the security feature sections
Xin this document; 3) follow the installation instructions (easy or
Xadvanced). I recommend that you first use the default security feature
Xsettings. Run the wrappers for a few days to become familiar with
Xtheir logs, before doing anything drastic such as cutting off access or
Xinstalling booby traps.
X
X2 - Disclaimer
X--------------
X
XThe wrapper programs rely on source address information obtained from
Xnetwork packets. Such information is not 100 percent reliable, although
Xthe wrappers do their best to expose forgeries.
X
XIn the absence of cryptographic protection of message contents, and of
Xcryptographic authentication of message originators, all data from the
Xnetwork should be treated with sound scepticism.
X
XTHIS RESTRICTION IS BY NO MEANS SPECIFIC TO THE TCP/IP PROTOCOLS.
X
X3 - Tutorials
X-------------
X
XThe tutorial sections give a gentle introduction to the operation of
Xthe wrapper programs, and introduce some of the terminology that is
Xused in the remainder of the document: client, server, the inetd and
Xsyslogd daemons, and their configuration files.
X
X3.1 - How it works
X------------------
X
XAlmost every application of the TCP/IP protocols is based on a client-
Xserver model. For example, when a user invokes the telnet command to
Xconnect to one of your systems, a telnet server process is executed on
Xthe target host. The telnet server process connects the user to a login
Xprocess. A few examples of client and server programs are shown in the
Xtable below:
X
X client server application
X --------------------------------
X telnet telnetd remote login
X ftp ftpd file transfer
X finger fingerd show users
X
XThe usual approach is to run one single daemon process that waits for
Xall kinds of incoming network connections. Whenever a connection is
Xestablished, this daemon (usually called inetd) runs the appropriate
Xserver program and goes back to sleep, waiting for other connections.
X
XThe wrapper programs rely on a simple, but powerful mechanism. Instead
Xof directly running the desired server program, the inetd is tricked
Xinto running a small wrapper program. The wrapper logs the remote host
Xname or address and performs some additional checks. When all is well,
Xthe wrapper executes the desired server program and goes away.
X
XThe wrapper programs have no interaction with the remote user (or
Xclient process). This has two major advantages: 1) the wrappers are
Xapplication-independent, so that the same program can protect many
Xkinds of network services; 2) no interaction also means that the
Xwrappers are invisible from outside (at least for regular users).
X
XAnother important property is that the wrapper programs are active only
Xwhen the initial contact between client and server is established. Once
Xa wrapper has done its work there is no overhead on the client-server
Xcommunication.
X
XThe simple mechanism has one major drawback: since the wrappers go away
Xafter the initial contact between client and server processes, the
Xwrappers are of little use with network daemons that service more than
Xone client. The wrappers would only see the first client attempt to
Xcontact such a server. The NFS mount daemon is a typical example of
Xa daemon that services requests from multiple clients.
X
XThere are two ways to use the wrapper programs:
X
X1) The easy way: move network daemons to some other directory and fill
X the resulting holes with copies of the wrapper programs. This
X approach involves no changes to configuration files, so there is
X very little risk of breaking things.
X
X2) The advanced way: leave the network daemons alone and modify the
X inetd configuration file. For example, an entry such as:
X
X tftp dgram udp wait root /usr/etc/tcpd in.tftpd -s /tftpboot
X
X When a tftp request arrives, inetd will run the wrapper program
X (tcpd) with a process name `in.tftpd'. This is the name that the
X wrapper will use when logging the request and when scanning the
X optional access control tables. `in.tftpd' is also the name of the
X server program that the wrapper will attempt to run when all is
X well. Any arguments (`-s /tftpboot' in this particular example) are
X transparently passed on to the server program.
X
XFor an account of the history of the wrapper programs, with real-life
Xexamples, see the section below on related documents.
X
X3.2 - Where the logging information goes
X----------------------------------------
X
XThe wrapper programs send their logging information to the syslog
Xdaemon (syslogd). The disposition of the wrapper logs is determined by
Xthe syslog configuration file (usually /etc/syslog.conf). Messages are
Xwritten to files, to the console, or are forwarded to a @loghost.
X
XOlder syslog implementations (still found on Ultrix systems) only
Xsupport priority levels ranging from 9 (debug-level messages) to 0
X(alerts). All logging information of the same priority level (or more
Xurgent) is written to the same destination. In the syslog.conf file,
Xpriority levels are specified in numerical form. For example,
X
X 8/usr/spool/mqueue/syslog
X
Xcauses all messages with priority 8 (informational messages), and
Xanything that is more urgent, to be appended to the file
X/usr/spool/mqueue/syslog.
X
XNewer syslog implementations support message classes in addition to
Xpriority levels. Examples of message classes are: mail, daemon, auth
Xand news. In the syslog.conf file, priority levels are specified with
Xsymbolic names: debug, info, notice, ..., emerg. For example,
X
X mail.debug /var/log/syslog
X
Xcauses all messages of class mail with priority debug (or more urgent)
Xto be appended to the /var/log/syslog file.
X
XBy default, the wrapper logs go to the same place as the transaction
Xlogs of the sendmail daemon. The disposition can be changed by editing
Xthe Makefile and/or the syslog.conf file. Send a `kill -HUP' to the
Xsyslogd after changing its configuration file. Remember that syslogd,
Xjust like sendmail, insists on one or more TABs between the left-hand
Xside and the right-hand side expressions in its configuration file.
X
X4 - Features
X------------
X
X4.1 - Access control
X--------------------
X
XWhen compiled with -DHOSTS_ACCESS, the wrapper programs support a
Xsimple form of access control. Access can be controlled per host, per
Xservice, or combinations thereof. The software provides hooks for the
Xexecution of shell commands when an access control rule fires; this
Xfeature may be used to install "booby traps". For details, see the
Xhosts_access.5 manual page, which is in `nroff -man' format. A later
Xsection describes how you can test your access control rules.
X
XAccess control is enabled by default. It can be turned off by editing
Xthe Makefile, or by providing no access control tables. The install
Xinstructions below describe the Makefile editing process.
X
X4.2 - Host name spoofing
X------------------------
X
XWith some network applications, such as RSH or RLOGIN, the remote host
Xname plays an important role in the authentication process. Host name
Xinformation can be reliable when lookups are done from a _local_ hosts
Xtable, provided that the client IP address can be trusted.
X
XWith _distributed_ name services, authentication schemes that rely on
Xhost names become more problematic. The security of your system now may
Xdepend on some far-away DNS (domain name server) outside your own
Xcontrol. Paradoxically, running NIS (YP) can actually improve hostname
Xsecurity because it provides you with the equivalent of a local hosts
Xfile.
X
XThe wrapper programs verify the remote host name that is returned by
Xthe address->name DNS server, by asking for a second opinion. To this
Xend, the programs look at the name and addresses that are returned by
Xthe name->address DNS server. If any discrepancies are found, the
Xwrappers conclude that at least one of the two name servers is lying,
Xand assume that they are dealing with a host that pretends to have
Xsomeone elses host name.
X
XWhen the wrappers are unable to verify the remote host name (the
Xaddress->name lookup succeeds but the name->address lookup fails), they
Xalso assume that the host name is wrong.
X
XWhen the remote host name is unavailable (the address->name lookup
Xfails) the wrappers just use the remote host address when logging the
Xconnection and when consulting the optional access control tables.
X
XWhen the sources are compiled with -DPARANOID, the wrappers will drop
Xthe connection in case of a host name/address mismatch. When the
Xsources are not compiled with -DPARANOID, the wrappers just pretend
Xthat the host name is unknown when logging the connection and when
Xconsulting the optional access control tables.
X
XParanoid mode is enabled by default. It can be turned off by editing
Xthe Makefile. The configuration and installation below describes the
XMakefile editing process.
X
X4.3 - Host address spoofing
X---------------------------
X
XWhile host name spoofing can be found out by asking a second opinion,
Xit is much harder to find out that a host claims to have someone elses
Xnetwork address. And since host names are deduced from network
Xaddresses, address spoofing is at least as effective as name spoofing.
X
XThe wrapper programs can give additional protection against hosts that
Xclaim to have an address that lies outside their own network. For
Xexample, some far-away host that claims to be a trusted host within
Xyour own network. Such things are possible even while the impersonated
Xsystem is up and running.
X
XThis additional protection is not an invention of my own; it has been
Xpresent for at least five years in the BSD rsh and rlogin daemons.
XUnfortunately, that feature was added *after* 4.3 BSD came out, so that
Xvery few, if any, UNIX vendors have adopted it. Our site, and many
Xother ones, has been running these enhanced daemons for several years,
Xand without any ill effects.
X
XWhen the programs are compiled with -DKILL_IP_OPTIONS, source routing
Xwill be disabled for all TCP connections that are handled by the
Xwrapper programs.
X
XAll this cannot be used with SunOS 4.x because of a kernel bug in the
Ximplementation of the getsockopt() system call. Kernel panics have been
Xreported for SunOS 4.1.1 and SunOS 4.1.2. The symptoms are "BAD TRAP"
Xand "Data fault" while executing the tcp_ctloutput() kernel function.
X
XThe feature is disabled by default. It can be turned on by editing the
XMakefile. The configuration and installation section below describes
Xthe Makefile editing process.
X
XUDP services do not benefit from this additional protection. With UDP,
Xall you can be certain of is the network packet's destination address.
X
X4.4 - Remote username lookups
X-----------------------------
X
XThe protocol proposed in RFC 931 provides a means to get the remote
Xuser name from the client host. The requirement is that the client
Xhost runs an RFC 931-compliant daemon. The information provided by such
Xa daemon is not intended to be used for authentication purposes, but it
Xcan provide additional information about the owner of a TCP connection.
X
XRemote user name lookups are enabled when the wrappers are compiled
Xwith -DRFC931. There are some limitations: the number of hosts that
Xrun an RFC 931 (or compatible) daemon is small (but growing); remote
Xuser name lookups do not work for datagram (UDP) connections. More
Xseriously, remote user name lookups can cause noticeable delays with
Xconnections from non-UNIX PCs. The wrappers use a 30-second timeout for
XRFC931 lookups, to accommodate slow networks and slow hosts.
X
XBy default, remote username lookups are not enabled. You can enable
Xthem by editing the Makefile. The remote username lookup timeout period
X(30 seconds default) can also be changed by editing the Makefile. The
Xinstallation sections below describe the Makefile editing process.
X
XThe RFC 931 protocol has diverged into different directions (IDENT and
XTAP). To add to the confusion, both protocols use the same network
Xport. The daemon wrappers implement a common subset of the protocols.
X
X4.5 - Language extension hooks
X------------------------------
X
XThe wrappers sport only a limited number of features. This is for a
Xgood reason: programs that are run at high privilege levels must be
Xeasy to verify.
X
XHowever, some sites have very specific needs. The options.c file
Xprovides a framework for adding extensions to the access control
Xlanguage. It comes with sample extensions that: (1) switch to another
Xuser or group id; (2) perform remote user name lookups; (3) run an
Xalternate server program (this allows you to produce customized bounce
Xmessages or to do really nasty stuff); (4) set arbitrary environment
Xvariables; (5) change the default file protection mask.
X
XThe language extension hook is not enabled by default because it
Xintroduces an incompatible change to the access control language
Xsyntax. Instructions to enable the extensions are given in the
XMakefile.
X
X5 - Other works
X---------------
X
X5.1 - Related documents
X-----------------------
X
XThe war story behind the wrapper tools is described in:
X
X W.Z. Venema, "TCP WRAPPER, network monitoring, access control and
X booby traps", UNIX Security Symposium III Proceedings (Baltimore),
X September 1992.
X
X ftp.win.tue.nl:/pub/security/tcp_wrapper.ps.Z (postscript)
X ftp.win.tue.nl:/pub/security/tcp_wrapper.txt.Z (flat text)
X
XThe same cracker is also described in:
X
X W.R. Cheswick, "An Evening with Berferd, In Which a Cracker is
X Lured, Endured, and Studied", Proceedings of the Winter USENIX
X Conference (San Francisco), January 1992.
X
X research.att.com:/dist/internet_security/berferd.ps
X
X5.2 - Related software
X----------------------
X
XNetwork daemons etc. with enhanced logging capabilities can generate
Xmassive amounts of information: our 100+ workstations generate several
Xhundred kbytes each day. egrep-based filters can help to suppress some
Xof the noise. A more powerful tool is the Swatch monitoring system by
XStephen E. Hansen and E. Todd Atkins. Swatch can process log files in
Xreal time and can associate arbitrary actions with patterns; its
Xapplications are by no means restricted to security. Swatch is
Xavailable from sierra.stanford.edu, directory /pub/sources.
X
XSocks, described in the UNIX Security III proceedings, can be used to
Xcontrol network traffic from hosts on an internal network, through a
Xfirewall host, to the outer world. Socks consists of a daemon that is
Xrun on the firewall host, and of a library with routines that redirect
Xapplication socket calls through the firewall daemon. Socks is
Xavailable from s1.gov in /pub/socks.tar.Z.
X
XVersions of rshd and rlogind, modified to report the remote user name
Xin addition to the remote host name, are available for anonymous ftp
X(ftp.win.tue.nl:/pub/security/logdaemon-2.tar.Z). These programs are
Xdrop-in replacements for SunOS 4.x, Ultrix 4.x, and SunOS 5.x.
X
XThe securelib shared library by William LeFebvre can be used to control
Xaccess to network daemons that are not run under control of the inetd,
Xsuch as the RPC daemons that run until the machine goes down.
XAvailable from eecs.nwu.edu, file /pub/securelib.tar.
X
XWhere shared libraries or router-based packet filtering are not an
Xoption, an alternative portmap daemon can help to improve RPC security,
Xin particular that of NFS and of the NIS (YP) information service.
Xftp.win.tue.nl:/pub/security/portmap.shar.Z was tested with SunOS 4.1.1
Xand 4.1.2, Ultrix 3.0 and Ultrix 4.x, HP-UX 8.x and AIX. The protection
Xis less effective than that of the securelib library because portmap is
Xmostly a dictionary service. SunOS 4.x users should install the latest
Xrevision of the portmap and NIS daemons instead, or adopt NIS+ which
Xhas access control built in.
X
XSource for a portable RFC 931 (TAP, IDENT)-compatible daemon by Peter
XEriksson is available from ftp.lysator.liu.se:/pub/ident/servers.
X
XSome TCP/IP implementations come without syslog library. Some come with
Xthe library but have no syslog daemon. A replacement can be found in
Xftp.win.tue.nl:/pub/security/surrogate-syslog.tar.Z. The fakesyslog
Xlibrary that comes with the nntp sources reportedly works well, too.
X
X6 - Limitations
X---------------
X
X6.1 - Known wrapper limitations
X-------------------------------
X
XSome UDP (and RPC) daemons linger around for a while after they have
Xserviced a request, just in case another request comes in. In the
Xinetd configuration file these daemons are registered with the `wait'
Xoption. Only the request that started such a daemon will be seen by the
Xwrappers. This restriction does not apply to connection-oriented (TCP)
Xservices.
X
XTLI (transport level interface), the System V stream-based and
Xprotocol-independent network programming interface, is not yet
Xsupported, but we're working on it.
X
XThe wrappers do not work with RPC services over TCP. These services are
Xregistered as rpc/tcp in the inetd configuration file. The only non-
Xtrivial service that is affected by this limitation is rexd, which is
Xused by the on(1) command. This is no great loss. On most systems,
Xrexd is less secure than a wildcard in /etc/hosts.equiv.
X
XRPC broadcast requests (for example: rwall, rup, rusers) always appear
Xto come from the responding host. What happens is that the client
Xbroadcasts its request to all portmap daemons on its network; each
Xportmap daemon forwards the request to its own system. As far as the
Xrwall etc. daemons know, the request comes from the local host.
X
XPortmap and RPC (e.g. NIS and NFS) security is a topic in itself. See
Xthe section in this document on related software.
X
X6.2 - Known system software bugs
X--------------------------------
X
XWorkarounds have been implemented for several bugs in system software.
XThey are described in the Makefile. Unfortunately, some system software
Xbugs cannot be worked around. The result is loss of functionality.
X
XOlder ConvexOS versions come with a broken recvfrom(2) implementation.
XThis makes it impossible for the daemon wrappers to look up the
Xremote host address (and hence, the name) in case of UDP requests.
XA patch is available for ConvexOS 10.1; later releases should be OK.
X
XOn some systems, the optional RFC 931 remote username lookups may
Xtrigger a kernel bug. When a client host connects to your system, and
Xthe RFC 931 connection from your system to that client is rejected by a
Xrouter, your kernel may drop all connections with that client. This is
Xnot a bug in the wrapper programs: complain to your vendor, and don't
Xenable remote user name lookups until the bug has been fixed.
X
XReportedly, SunOS 4.1.1, Next 2.0a, ISC 3.0 with TCP 1.3, and AIX 3.2.2
Xare OK.
X
XSony News/OS 4.51, HP-UX 8-something and Ultrix 4.3 still have the bug.
XAt the time of writing, a fix for Ultrix is being field tested (CXO-8919).
X
XThe following procedure can be used (from outside the tue.nl domain) to
Xfind out if your kernel has the bug. From the system under test, do:
X
X % ftp 131.155.70.100
X
XThis command attempts to make an ftp connection to our anonymous ftp
Xserver (ftp.win.tue.nl). When the connection has been established, run
Xthe following command from the same system under test, while keeping
Xthe ftp connection open:
X
X % telnet 131.155.70.100 111
X
XDo not forget the `111' at the end of the command. This telnet command
Xattempts to connect to our portmap process. The telnet command should
Xfail with: "host not reachable", or something like that. If your ftp
Xconnection gets messed up, you have the bug. If the telnet command does
Xnot fail, please let me know a.s.a.p.!
X
XFor those who care, the bug is that the BSD kernel code was not careful
Xenough with incoming ICMP UNREACHABLE control messages (it ignored the
Xlocal and remote port numbers). The bug is still present in the BSD
XNET/1 source release (1989) but apparently has been fixed in BSD NET/2
X(1991). You can see it with your own eyes, if you have the courage.
X
X7 - Configuration and installation
X----------------------------------
X
X7.1 - Easy configuration and installation
X-----------------------------------------
X
XThe "easy" recipe requires no changes to existing software or
Xconfiguration files. Basically, you move the daemons that you want to
Xprotect to a different directory and plug the resulting holes with
Xcopies of the wrapper programs.
X
XIf you don't run Ultrix, you won't need the miscd wrapper program. The
Xmiscd daemon implements among others the SYSTAT service, which produces
Xthe same output as the the WHO command.
X
XCopy the file Makefile.dist to Makefile, edit the Makefile according to
Xthe instructions at the beginning of that file, and type `make'.
X
XWhen the `make' succeeds the result is two executables (maybe three in
Xcase of Ultrix). The `try' program can be used to play with host access
Xcontrol tables and is described in a later section.
X
XThe tcpd program can be used to monitor the telnet, finger, ftp, exec,
Xrsh, rlogin, tftp, talk, comsat and other tcp or udp services that have
Xa one-to-one mapping onto executable files.
X
XThe tcpd program can also be used for services that are marked as
Xrpc/udp in the inetd configuration file, but not for rpc/tcp services
Xsuch as rexd. You probably do not want to run rexd anyway. On most
Xsystems it is even less secure than a wildcard in /etc/hosts.equiv.
X
XThe wrappers are not yet able to deal with TLI-based services.
X
XDecide which services you want to monitor. Move the corresponding
Xvendor-provided daemon programs to the location specified by the
XREAL_DAEMON_DIR constant in the Makefile, and fill the holes with
Xcopies of the tcpd wrapper. That is, one copy of (or link to) the tcpd
Xprogram for each service that you want to monitor. For example, to
Xmonitor the use of your finger service:
X
X # mkdir REAL_DAEMON_DIR
X # mv /usr/etc/in.fingerd REAL_DAEMON_DIR
X # cp tcpd /usr/etc/in.fingerd
X
XThe example applies to SunOS 4. With other UNIX implementations the
Xnetwork daemons live in /usr/libexec or /usr/sbin, or have no "in."
Xprefix to their names, but you get the idea.
X
XUltrix only: If you want to monitor the SYSTAT service, move the
Xvendor-provided miscd daemon to the location specified by the
XREAL_MISCD macro in the Makefile, and install the miscd wrapper into
Xthe original miscd location.
X
XIn the absence of any access-control tables, the daemon wrappers
Xwill just maintain a record of network connections made to your system.
X
X7.2 - Advanced configuration and installation
X---------------------------------------------
X
XThe advanced recipe leaves your daemon executables alone, but involves
Xsimple modifications to the inetd configuration file.
X
XCopy the file Makefile.dist to Makefile. In the Makefile, define the
XREAL_DAEMON_DIR macro (if you run Ultrix, the REAL_MISCD macro, too) to
Xreflect the path to your existing network daemons. Don't panic when
Xsome daemons live elsewhere; we'll deal with that later. Have a look
Xat the other instructions in the Makefile and type `make'.
X
XWhen the `make' succeeds the result is two executables (maybe three in
Xcase of Ultrix). The `try' program can be used to play with host access
Xcontrol tables and is described in a later section.
X
XThe tcpd program can be used to monitor the telnet, finger, ftp, exec,
Xrsh, rlogin, tftp, talk, comsat and other tcp or udp services that have
Xa one-to-one mapping onto executable files.
X
XThe tcpd program can also be used for services that are marked as
Xrpc/udp in the inetd configuration file, but not for rpc/tcp services
Xsuch as rexd. You probably do not want to run rexd anyway. On most
Xsystems it is even less secure than a wildcard in /etc/hosts.equiv.
X
XThe wrappers are not yet able to deal with TLI-based services.
X
XInstall the tcpd command in a suitable place. Apollo UNIX users will
Xwant to install it under a different name because the name "tcpd" is
Xalready taken; a suitable name for the wrapper program would be
X"frontd". Then perform the following edits on the inetd configuration
Xfile (usually /etc/inetd.conf or /etc/inet/inetd.conf):
X
X finger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
X
Xbecomes:
X
X finger stream tcp nowait nobody /usr/etc/tcpd in.fingerd
X
XSend a `kill -HUP' to the inetd process to make the change effective.
X
XThe example applies to SunOS 4. With other UNIX implementations the
Xnetwork daemons live in /usr/libexec or /usr/sbin, the network daemons
Xhave no "in." prefix to their names, or the username field in the inetd
Xconfiguration file may be missing.
X
XWhen the finger service works as expected you can perform similar
Xchanges for other network services. Do not forget the `kill -HUP'.
X
XThe miscd daemon that comes with Ultrix implements several network
Xservices. It decides what to do by looking at its process name. One of
Xthe services is systat, which is a kind of limited finger service. If
Xyou want to monitor the systat service, install the miscd wrapper in
Xa suitable place and update the inetd configuration file:
X
X systat stream tcp nowait /suitable/place/miscd systatd
X
XUltrix 4.3 allows you to specify a user id under which the daemon will
Xbe executed. This feature is not documented in the manual pages. Thus,
Xthe example would become:
X
X systat stream tcp nowait nobody /suitable/place/miscd systatd
X
XOlder Ultrix systems still run all their network daemons as root.
X
XIn the absence of any access-control tables, the daemon wrappers
Xwill just maintain a record of network connections made to your system.
X
X7.3 - Daemons with arbitrary path names
X---------------------------------------
X
XThe above tcpd examples work fine with network daemons that live in a
Xcommon directory, but sometimes that is not practical. Having soft
Xlinks all over your file system is not a clean solution, either.
X
XInstead you can specify, in the inetd configuration file, an absolute
Xpath name for the daemon process name. For example,
X
X ntalk dgram udp wait root /usr/etc/tcpd /usr/local/lib/ntalkd
X
XWhen the daemon process name is an absolute path name, tcpd ignores the
Xvalue of the REAL_DAEMON_DIR constant, and uses the last path component
Xof the daemon process name for logging and for access control.
X
X7.4 - Building and testing the access control rules
X---------------------------------------------------
X
XIn order to support access control the wrappers must be compiled with
Xthe -DHOSTS_ACCESS option. The access control policy is given in the
Xform of two tables (default: /etc/hosts.allow and /etc/hosts.deny).
XAccess control is disabled when there are no access control tables, or
Xwhen the tables are empty.
X
XIf you haven't used the wrappers before I recommend that you first run
Xthem a couple of days without any access control restrictions. The
Xlogfile records should give you an idea of the process names and of the
Xhost names that you will have to build into your access control rules.
X
XThe syntax of the access control rules is documented in the file
Xhosts_access.5, which is in `nroff -man' format. This is a lengthy
Xdocument, and no-one expects you to read it right away from beginning
Xto end. Instead, after reading the introductory section, skip to the
Xexamples at the end so that you get a general idea of the language.
XThen you can appreciate the detailed reference sections near the
Xbeginning of the document.
X
XThe examples in the hosts_access.5 document show two specific types of
Xaccess control policy: 1) mostly closed (only permitting access from a
Xlimited number of systems) and 2) mostly open (permitting access from
Xeveryone except a limited number of trouble makers). You will have to
Xchoose what model suits your situation best. Implementing a mixed
Xpolicy should not be overly difficult either.
X
XThe `try' command can be used to try out your local access control
Xfiles. The command syntax is:
X
X ./try process_name hostname (e.g.: ./try in.tftpd localhost)
X
X ./try process_name address (e.g.: ./try in.tftpd 127.0.0.1)
X
XIn order to find out what process name to use, just use the service and
Xwatch the process name that shows up in the logfile. Alternatively,
Xyou can look up the name from the inetd configuration file. Coming back
Xto the tftp example in the tutorial section above:
X
X tftp dgram udp wait root /usr/etc/tcpd in.tftpd -s /tftpboot
X
XThis entry causes the inetd to run the wrapper program (tcpd) with a
Xprocess name `in.tftpd'. This is the name that the wrapper will use
Xwhen scanning the access control tables. Therefore, `in.tftpd' is the
Xprocess name that should be given to the `try' command. On your system
Xthe actual inetd.conf entry may differ (tftpd instead of in.tftpd, and
Xno `root' field), but you get the idea.
X
XWhen you specify a host name, the `try' program will use both the host
Xname and address. This way you can simulate the most common case where
Xthe wrappers know both the host address and the host name. The `try'
Xprogram will iterate over all addresses that it can find for the given
Xhost name.
X
XWhen you specify a host address instead of a host name, the `try'
Xprogram will pretend that the host name is unknown, so that you can
Xsimulate what happens when the wrapper is unable to look up the remote
Xhost name.
X
XSerious errors in the configuration file syntax will be reported via
Xthe syslog daemon. Run a `tail -f' on the logfile while playing with
Xthe `try' command. The tutorial section at the beginning of this file
Xdescribes where to look for your logfile.
X
X7.5 - Other applications
X------------------------
X
XThe access control routines can easily be integrated with other
Xprograms. The hosts_access.3 manual page (`nroff -man' format)
Xdescribes the external interface of the libwrap.a library.
X
XThe tcpd wrapper can even be used to control access to the smtp port.
XIn that case, sendmail should not be run as a stand-alone daemon, but
Xit should be registered in the inetd configuration file. For example:
X
X smtp stream tcp nowait root /usr/etc/tcpd /usr/lib/sendmail -bs
X
XYou will periodically want to run sendmail to process queued-up
Xmessages. A crontab entry like:
X
X 0,15,30,45 * * * * /usr/lib/sendmail -q
X
Xshould take care of that. When you are going to "protect" your sendmail
Xdaemon this way, you should realize that there are many "unprotected"
Xsendmail daemons all over the network that can still be abused.
X
X8 - Acknowledgements
X--------------------
X
XMany people contributed to the evolution of the programs, by asking
Xinspiring questions, by suggesting features or bugfixes, or by
Xsubmitting source code. Nevertheless, all mistakes and bugs in the
Xwrappers are my own.
X
XThanks to Brendan Kehoe (brendan@cs.widener.edu), Heimir Sverrisson
X(heimir@hafro.is) and Dan Bernstein (brnstnd@kramden.acf.nyu.edu) for
Xfeedback on an early release of this product. The host name/address
Xcheck was suggested by John Kimball (jkimball@src.honeywell.com).
XApollo's UNIX environment has some peculiar quirks: Willem-Jan Withagen
X(wjw@eb.ele.tue.nl), Pieter Schoenmakers (tiggr@es.ele.tue.nl) and
XCharles S. Fuller (fuller@wccs.psc.edu) provided assistance. Hal R.
XBrand (BRAND@addvax.llnl.gov) told me how to get the remote IP address
Xin case of datagram-oriented services, and suggested the optional shell
Xcommand feature. Shabbir Safdar (shabby@mentor.cc.purdue.edu) provided
Xa first version of a much-needed manual page. Granville Boman Goza, IV
X(gbg@sei.cmu.edu) suggested to use the remote IP address even when the
Xhost name is available. Casper H.S. Dik (casper@fwi.uva.nl) provided
Xadditional insight into DNS spoofing techniques. The bogus daemon
Xfeature was inspired by code from Andrew Macpherson (BNR Europe Ltd).
XSteve Bellovin (smb@research.att.com) confirmed some of my suspicions
Xabout the darker sides of TCP/IP insecurity.
X
XIn no particular order, Howard Chu (hyc@hanauma.jpl.nasa.gov), John P.
XRouillard (rouilj@cs.umb.edu), Darren Reed (avalon@coombs.anu.edu.au),
XIcarus Sparry (I.Sparry@gdr.bath.ac.uk), Scott Schwartz (schwartz@
Xcs.psu.edu), John A. Kunze (jak@violet.berkeley.edu), Daniel Len
XSchales (dan@engr.latech.edu), Chris Turbeville <turbo@cse.uta.edu>,
XPaul Kranenburg <pk@cs.few.eur.nl>, and many, many others provided
Xfixes, code fragments, or other improvements to the wrappers.
X
X Wietse Venema (wietse@wzv.win.tue.nl)
X Department of Mathematics and Computing Science
X Eindhoven University of Technology
X P.O. Box 513
X 5600 MB Eindhoven
X The Netherlands
END_OF_README
if test 34888 -ne `wc -c <README`; then
echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f miscd.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"miscd.c\"
else
echo shar: Extracting \"miscd.c\" \(2602 characters\)
sed "s/^X//" >miscd.c <<'END_OF_miscd.c'
X /*
X * Front end to the ULTRIX miscd service. The front end logs the remote host
X * name and then invokes the real miscd daemon. Install as "/usr/etc/miscd",
X * after moving the real miscd daemon to the "/usr/etc/..." directory.
X * Connections and diagnostics are logged through syslog(3).
X *
X * The Ultrix miscd program implements (among others) the systat service, which
X * pipes the output from who(1) to stdout. This information is potentially
X * useful to systems crackers.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) miscd.c 1.4 93/03/07 22:47:28";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <syslog.h>
X
X/* Local stuff. */
X
X#include "patchlevel.h"
X#include "log_tcp.h"
X
X/* The following specifies where the vendor-provided daemon should go. */
X
X#ifndef REAL_MISCD
X#define REAL_MISCD "/usr/etc/.../miscd"
X#endif
X
Xint log_severity = SEVERITY; /* run-time adjustable */
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X struct from_host from;
X int from_stat;
X
X /* Attempt to prevent the creation of world-writable files. */
X
X#ifdef DAEMON_UMASK
X umask(DAEMON_UMASK);
X#endif
X
X /*
X * Open a channel to the syslog daemon. Older versions of openlog()
X * require only two arguments.
X */
X
X#ifdef LOG_MAIL
X (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X (void) openlog(argv[0], LOG_PID);
X#endif
X
X /*
X * Find out and verify the remote host name. Sites concerned with
X * security may choose to refuse connections from hosts that pretend to
X * have someone elses host name.
X */
X
X from_stat = fromhost(&from);
X#ifdef PARANOID
X if (from_stat == -1)
X refuse(&from);
X#endif
X
X /*
X * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
X * socket options at the IP level. They do so for a good reason. Let's
X * follow their example.
X */
X
X#ifdef KILL_IP_OPTIONS
X fix_options(&from);
X#endif
X
X /*
X * Check whether this host can access the service in argv[0]. The
X * access-control code invokes optional shell commands as specified in
X * the access-control tables.
X */
X
X#ifdef HOSTS_ACCESS
X if (!hosts_access(argv[0], &from))
X refuse(&from);
X#endif
X
X /* Report remote client and invoke the real daemon program. */
X
X syslog(log_severity, "connect from %s", hosts_info(&from));
X (void) execv(REAL_MISCD, argv);
X syslog(LOG_ERR, "%s: %m", REAL_MISCD);
X clean_exit(&from);
X /* NOTREACHED */
X}
END_OF_miscd.c
if test 2602 -ne `wc -c <miscd.c`; then
echo shar: \"miscd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tcpd.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"tcpd.c\"
else
echo shar: Extracting \"tcpd.c\" \(2995 characters\)
sed "s/^X//" >tcpd.c <<'END_OF_tcpd.c'
X /*
X * General front end for stream and datagram IP services. This program logs
X * the remote host name and then invokes the real daemon. For example,
X * install as /usr/etc/{tftpd,fingerd,telnetd,ftpd,rlogind,rshd,rexecd},
X * after saving the real daemons in the directory "/usr/etc/...". This
X * arrangement requires that the network daemons are started by inetd or
X * something similar. Connections and diagnostics are logged through
X * syslog(3).
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) tcpd.c 1.4 93/03/07 22:47:32";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strrchr();
Xextern char *strcpy();
X
X#ifndef MAXPATHNAMELEN
X#define MAXPATHNAMELEN BUFSIZ
X#endif
X
X/* Local stuff. */
X
X#include "patchlevel.h"
X#include "log_tcp.h"
X
X/* The following specifies where the vendor-provided daemons should go. */
X
X#ifndef REAL_DAEMON_DIR
X#define REAL_DAEMON_DIR "/usr/etc/..."
X#endif
X
Xint log_severity = SEVERITY; /* run-time adjustable */
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X struct from_host from;
X int from_stat;
X char path[MAXPATHNAMELEN];
X
X /* Attempt to prevent the creation of world-writable files. */
X
X#ifdef DAEMON_UMASK
X umask(DAEMON_UMASK);
X#endif
X
X /*
X * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip
X * argv[0] to its basename.
X */
X
X if (argv[0][0] == '/') {
X strcpy(path, argv[0]);
X argv[0] = strrchr(argv[0], '/') + 1;
X } else {
X sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
X }
X
X /*
X * Open a channel to the syslog daemon. Older versions of openlog()
X * require only two arguments.
X */
X
X#ifdef LOG_MAIL
X (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X (void) openlog(argv[0], LOG_PID);
X#endif
X
X /*
X * Find out and verify the remote host name. Sites concerned with
X * security may choose to refuse connections from hosts that pretend to
X * have someone elses host name.
X */
X
X from_stat = fromhost(&from);
X#ifdef PARANOID
X if (from_stat == -1)
X refuse(&from);
X#endif
X
X /*
X * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
X * socket options at the IP level. They do so for a good reason. Let's
X * follow their example.
X */
X
X#ifdef KILL_IP_OPTIONS
X fix_options(&from);
X#endif
X
X /*
X * Check whether this host can access the service in argv[0]. The
X * access-control code invokes optional shell commands as specified in
X * the access-control tables.
X */
X
X#ifdef HOSTS_ACCESS
X if (!hosts_access(argv[0], &from))
X refuse(&from);
X#endif
X
X /* Report remote client and invoke the real daemon program. */
X
X syslog(log_severity, "connect from %s", hosts_info(&from));
X (void) execv(path, argv);
X syslog(LOG_ERR, "%s: %m", path);
X clean_exit(&from);
X /* NOTREACHED */
X}
END_OF_tcpd.c
if test 2995 -ne `wc -c <tcpd.c`; then
echo shar: \"tcpd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fromhost.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"fromhost.c\"
else
echo shar: Extracting \"fromhost.c\" \(8144 characters\)
sed "s/^X//" >fromhost.c <<'END_OF_fromhost.c'
X /*
X * fromhost() determines the type of connection (datagram, stream), the name
X * and address of the host at the other end of standard input, and the
X * remote user name (if RFC 931 lookups are enabled). A host name of "stdin"
X * is returned if the program is run from a tty. The value "unknown" is
X * returned as a placeholder for information that could not be looked up.
X * All results are in static memory.
X *
X * The return status is (-1) if the remote host pretends to have someone elses
X * host name, otherwise a zero status is returned.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) fromhost.c 1.7 93/03/07 22:47:34";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <errno.h>
X
Xextern char *inet_ntoa();
Xextern char *strncpy();
Xextern char *strcpy();
X
X/* In case not defined in <sys/param.h>. */
X
X#ifndef MAXHOSTNAMELEN
X#define MAXHOSTNAMELEN 1024 /* string with host name */
X#endif
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Forward declarations. */
X
Xstatic int matchname();
X
X/* The following are to be used in assignment context, not in comparisons. */
X
X#define GOOD 1
X#define BAD 0
X
X/* Initially, we know nothing about the origin of the connection. */
X
Xstatic struct from_host from_unknown = {
X 0, /* connected/unconnected */
X FROM_UNKNOWN, /* remote host name */
X FROM_UNKNOWN, /* remote host address */
X "", /* remote user name */
X};
X
X /*
X * With early SunOS 5 versions, recvfrom() does not completely fill in the
X * source address structure when doing a non-destructive read. The following
X * code works around the problem. It does no harm on "normal" systems.
X */
X
X#ifdef RECVFROM_BUG
X
Xstatic int fix_recvfrom(sock, buf, buflen, flags, from, fromlen)
Xint sock;
Xchar *buf;
Xint buflen;
Xint flags;
Xstruct sockaddr *from;
Xint *fromlen;
X{
X int ret;
X
X /* Assume that both ends of a socket belong to the same address family. */
X
X if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) {
X if (from->sa_family == 0) {
X struct sockaddr my_addr;
X int my_addr_len = sizeof(my_addr);
X
X if (getsockname(0, &my_addr, &my_addr_len)) {
X syslog(LOG_ERR, "getsockname: %m");
X } else {
X from->sa_family = my_addr.sa_family;
X }
X }
X }
X return (ret);
X}
X
X#define recvfrom fix_recvfrom
X#endif
X
X /*
X * The Apollo SR10.3 and some SYSV4 getpeername(2) versions do not return an
X * error in case of a datagram-oriented socket. Instead, they claim that all
X * UDP requests come from address 0.0.0.0. The following code works around
X * the problem. It does no harm on "normal" systems.
X */
X
X#ifdef GETPEERNAME_BUG
X
Xstatic int fix_getpeername(sock, sa, len)
Xint sock;
Xstruct sockaddr *sa;
Xint *len;
X{
X int ret;
X struct sockaddr_in *sin = (struct sockaddr_in *) sa;
X
X if ((ret = getpeername(sock, sa, len)) >= 0
X && sa->sa_family == AF_INET
X && sin->sin_addr.s_addr == 0) {
X errno = ENOTCONN;
X return (-1);
X } else {
X return (ret);
X }
X}
X
X#define getpeername fix_getpeername
X#endif
X
X/* fromhost - find out what is at the other end of standard input */
X
Xint fromhost(f)
Xstruct from_host *f;
X{
X static struct sockaddr sa;
X struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X struct hostent *hp;
X int length = sizeof(sa);
X char buf[BUFSIZ];
X static char addr_buf[FROM_ADDRLEN];
X static char name_buf[MAXHOSTNAMELEN];
X
X /*
X * There are so many results and so many early returns that it seems
X * safest to first initialize all results to UNKNOWN.
X */
X
X *f = from_unknown;
X
X /*
X * Look up the remote host address. Hal R. Brand <BRAND@addvax.llnl.gov>
X * suggested how to get the remote host info in case of UDP connections:
X * peek at the first message without actually looking at its contents.
X */
X
X if (getpeername(0, &sa, &length) >= 0) { /* assume TCP request */
X f->sock_type = FROM_CONNECTED;
X } else {
X switch (errno) {
X default:
X if (isatty(0)) /* stdin is not a socket */
X f->name = "stdin";
X else
X syslog(LOG_ERR, "getpeername: %m"); /* other, punt */
X return (0);
X case ENOTCONN: /* assume UDP request */
X length = sizeof(sa);
X if (recvfrom(0, buf, sizeof(buf), MSG_PEEK, &sa, &length) < 0) {
X syslog(LOG_ERR, "recvfrom: %m");
X return (0);
X }
X#ifdef really_paranoid
X memset(buf, 0 sizeof(buf));
X#endif
X f->sock_type = FROM_UNCONNECTED;
X break;
X }
X }
X
X /*
X * At present, we can only deal with the AF_INET address family. Some
X * implementations of System V religion never fill in the address family
X * field in case of UDP connections. If that happens, you may want to
X * take the chance and assume that we're dealing with TCP/IP anyway.
X */
X
X#ifdef ADDRESS_FAMILY_BUG
X if (sa.sa_family == 0)
X sa.sa_family = AF_INET;
X#endif
X if (sa.sa_family != AF_INET) {
X syslog(LOG_ERR, "unexpected address family %ld", (long) sa.sa_family);
X return (0);
X }
X /* Save the host address. A later inet_ntoa() call may clobber it. */
X
X f->sin = sin;
X f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
X
X /* Look up the remote user name. Does not work for UDP services. */
X
X#if defined(RFC931) && !defined(USER_AT_HOST) && !defined(RFC931_OPTION)
X if (f->sock_type == FROM_CONNECTED)
X f->user = rfc931_name(sin);
X#endif
X
X /* Look up the remote host name. */
X
X if ((hp = gethostbyaddr((char *) &sin->sin_addr,
X sizeof(sin->sin_addr),
X AF_INET)) == 0) {
X return (0);
X }
X /* Save the host name. A later gethostbyxxx() call may clobber it. */
X
X f->name = strncpy(name_buf, hp->h_name, sizeof(name_buf) - 1);
X name_buf[sizeof(name_buf) - 1] = 0;
X
X /*
X * Verify that the host name does not belong to someone else. If host
X * name verification fails, pretend that the host name lookup failed.
X */
X
X if (matchname(f->name, sin->sin_addr)) {
X return (0);
X } else {
X f->name = FROM_UNKNOWN;
X return (-1); /* verification failed */
X }
X}
X
X/* matchname - determine if host name matches IP address */
X
Xstatic int matchname(remotehost, addr)
Xchar *remotehost;
Xstruct in_addr addr;
X{
X struct hostent *hp;
X int i;
X
X if ((hp = gethostbyname(remotehost)) == 0) {
X
X /*
X * Unable to verify that the host name matches the address. This may
X * be a transient problem or a botched name server setup. We decide
X * to play safe.
X */
X
X syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
X return (BAD);
X
X } else {
X
X /*
X * Make sure that gethostbyname() returns the "correct" host name.
X * Unfortunately, gethostbyname("localhost") sometimes yields
X * "localhost.domain". Since the latter host name comes from the
X * local DNS, we just have to trust it (all bets are off if the local
X * DNS is perverted). We always check the address list, though.
X */
X
X if (strcasecmp(remotehost, hp->h_name)
X && strcasecmp(remotehost, "localhost")) {
X syslog(LOG_ERR, "host name/name mismatch: %s != %s",
X remotehost, hp->h_name);
X return (BAD);
X }
X /* Look up the host address in the address list we just got. */
X
X for (i = 0; hp->h_addr_list[i]; i++) {
X if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
X return (GOOD);
X }
X
X /*
X * The host name does not map to the original host address. Perhaps
X * someone has compromised a name server. More likely someone botched
X * it, but that could be dangerous, too.
X */
X
X syslog(LOG_ERR, "host name/address mismatch: %s != %s",
X inet_ntoa(addr), hp->h_name);
X return (BAD);
X }
X}
X
X#ifdef TEST
X
X/* Code for stand-alone testing. */
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X struct from_host from;
X
X#ifdef LOG_MAIL
X (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X (void) openlog(argv[0], LOG_PID);
X#endif
X (void) fromhost(&from);
X printf("%s\n", hosts_info(&from));
X return (0);
X}
X
X#endif
END_OF_fromhost.c
if test 8144 -ne `wc -c <fromhost.c`; then
echo shar: \"fromhost.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"hosts_access.c\"
else
echo shar: Extracting \"hosts_access.c\" \(11173 characters\)
sed "s/^X//" >hosts_access.c <<'END_OF_hosts_access.c'
X /*
X * This module implements a simple access control language that is based on
X * host (or domain) names, netgroup, internet addresses (or network numbers)
X * and daemon process names. When a match is found an optional shell command
X * is executed and the search is terminated.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Compile with -DNETGROUP if your library provides support for netgroups.
X *
X * Compile with -DUSER_AT_HOST for rule-driven username lookups.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_access.c 1.10 93/03/07 22:47:36";
X#endif
X
X /* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <ctype.h>
X#include <errno.h>
X
Xextern char *fgets();
Xextern char *strchr();
Xextern char *strtok();
X
X#ifndef INADDR_NONE
X#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
X#endif
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X#ifdef INET_ADDR_BUG
X#include "inet_addr_fix"
X#endif
X
X/* Delimiters for lists of daemons or clients. */
X
Xstatic char sep[] = ", \t";
X
X/* Constants to be used in assignments only, not in comparisons... */
X
X#define YES 1
X#define NO 0
X#define FAIL (-1)
X
X/* Forward declarations. */
X
Xstatic int table_match();
Xstatic int list_match();
Xstatic int client_match();
Xstatic int string_match();
Xstatic int masked_match();
Xstatic char *xgets();
X
X/* The user@host access control. Trivial to add but complicates use. */
X
X#ifdef USER_AT_HOST
Xstatic int userhost_match();
X#define CLIENT_MATCH userhost_match
X#else
X#define CLIENT_MATCH client_match
X#endif
X
X/* Size of logical line buffer. */
X
X#define BUFLEN 2048
X
X/* hosts_access - host access control facility */
X
Xint hosts_access(daemon, client)
Xchar *daemon;
Xstruct from_host *client; /* host or user name may be empty */
X{
X
X /*
X * If the (daemon, client) pair is matched by an entry in the file
X * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
X * client) pair is matched by an entry in the file /etc/hosts.deny,
X * access is denied. Otherwise, access is granted. A non-existent
X * access-control file is treated as an empty file.
X */
X
X if (table_match(HOSTS_ALLOW, daemon, client))
X return (YES);
X if (table_match(HOSTS_DENY, daemon, client))
X return (NO);
X return (YES);
X}
X
X/* table_match - match table entries with (daemon, client) pair */
X
Xstatic int table_match(table, daemon, client)
Xchar *table;
Xchar *daemon;
Xstruct from_host *client; /* host or user name may be empty */
X{
X FILE *fp;
X char sv_list[BUFLEN]; /* becomes list of daemons */
X char *cl_list; /* becomes list of clients */
X char *sh_cmd; /* becomes optional shell command */
X int match;
X int end;
X
X /* The following variables should always be tested together. */
X
X int sv_match = NO; /* daemon matched */
X int cl_match = NO; /* client matced */
X
X /*
X * Process the table one logical line at a time. Lines that begin with a
X * '#' character are ignored. Non-comment lines are broken at the ':'
X * character (we complain if there is none). The first field is matched
X * against the daemon process name (argv[0]), the second field against
X * the host name or address. A non-existing table is treated as if it
X * were an empty table. The search terminates at the first matching rule.
X * When a match is found an optional shell command is executed.
X */
X
X if (fp = fopen(table, "r")) {
X while (!(sv_match && cl_match) && xgets(sv_list, sizeof(sv_list), fp)) {
X if (sv_list[end = strlen(sv_list) - 1] != '\n') {
X syslog(LOG_ERR, "%s: missing newline or line too long", table);
X continue;
X }
X if (sv_list[0] == '#') /* skip comments */
X continue;
X while (end > 0 && isspace(sv_list[end - 1]))
X end--;
X sv_list[end] = '\0'; /* strip trailing whitespace */
X if (sv_list[0] == 0) /* skip blank lines */
X continue;
X if ((cl_list = strchr(sv_list, ':')) == 0) {
X syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
X continue;
X }
X *cl_list++ = '\0'; /* split 1st and 2nd fields */
X if ((sh_cmd = strchr(cl_list, ':')) != 0)
X *sh_cmd++ = '\0'; /* split 2nd and 3rd fields */
X if ((sv_match = list_match(sv_list, daemon, string_match)))
X cl_match = list_match(cl_list, (char *) client, CLIENT_MATCH);
X }
X (void) fclose(fp);
X } else if (errno != ENOENT) {
X syslog(LOG_ERR, "cannot open %s: %m", table);
X }
X match = (sv_match == YES && cl_match == YES);
X if (match && sh_cmd)
X OPTIONS_STYLE(sh_cmd, daemon, client);
X return (match);
X}
X
X/* list_match - match an item against a list of tokens with exceptions */
X
Xstatic int list_match(list, item, match_fn)
Xchar *list;
Xchar *item;
Xint (*match_fn) ();
X{
X char *tok;
X int match = NO;
X
X /*
X * Process tokens one at a time. We have exhausted all possible matches
X * when we reach an "EXCEPT" token or the end of the list. If we do find
X * a match, look for an "EXCEPT" list and recurse to determine whether
X * the match is affected by any exceptions.
X */
X
X for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
X if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
X break;
X if (match = (*match_fn) (tok, item)) /* YES or FAIL */
X break;
X }
X /* Process exceptions to YES or FAIL matches. */
X
X if (match != NO) {
X while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
X /* VOID */ ;
X if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
X return (match);
X }
X return (NO);
X}
X
X/* client_match - match host name and address against token */
X
Xstatic int client_match(tok, item)
Xchar *tok;
Xchar *item;
X{
X struct from_host *client = (struct from_host *) item;
X int match;
X
X /*
X * Try to match the address first. If that fails, try to match the host
X * name if available.
X */
X
X if ((match = string_match(tok, client->addr)) == 0)
X if (client->name[0] != 0)
X match = string_match(tok, client->name);
X return (match);
X}
X
X#ifdef USER_AT_HOST
X
X/* userhost_match - do user@host access control */
X
Xstatic int userhost_match(tok, item)
Xchar *tok;
Xchar *item;
X{
X struct from_host *client = (struct from_host *) item;
X int match = NO;
X char *at;
X int host_match;
X int user_match;
X
X /*
X * Warning: experimental code, enabled only when USER_AT_HOST is defined.
X *
X * Basically, you specify user_pattern@host_pattern where remote username
X * lookups are desired, and plain host_pattern for all other cases. The
X * syntax of user name patterns is the same as for hosts or daemons, but
X * ALL is probably the only user_pattern that makes sense.
X *
X * In case of UDP connections, the result of username lookup will always be
X * "unknown".
X *
X * Return FAIL if we match a pattern of the form user@FAIL or FAIL@host:
X * FAIL, like NO, is transitive. According to some people, such patterns
X * should be taken out and shot. Good news: FAIL is on its way out.
X */
X
X if (at = strchr(tok + 1, '@')) { /* user@host */
X *at = 0;
X if (host_match = client_match(at + 1, item)) {
X if (client->user[0] == 0) {
X if (client->sock_type != FROM_CONNECTED) {
X client->user = FROM_UNKNOWN;
X } else if (client->sin == 0) {
X syslog(LOG_ERR, "no socket info for user name lookup");
X client->user = FROM_UNKNOWN;
X } else {
X client->user = rfc931_name(client->sin);
X }
X }
X user_match = string_match(tok, client->user);
X if (user_match == NO || user_match == FAIL) {
X match = user_match;
X } else {
X match = host_match;
X }
X }
X *at = '@';
X } else { /* host */
X match = client_match(tok, item);
X }
X return (match);
X}
X
X#endif /* USER_AT_HOST */
X
X/* string_match - match string against token */
X
Xstatic int string_match(tok, string)
Xchar *tok;
Xchar *string;
X{
X int tok_len;
X int str_len;
X char *cut;
X#ifdef NETGROUP
X static char *mydomain = 0;
X#endif
X
X /*
X * Return YES if a token has the magic value "ALL". Return FAIL if the
X * token is "FAIL". If the token starts with a "." (domain name), return
X * YES if it matches the last fields of the string. If the token has the
X * magic value "LOCAL", return YES if the string does not contain a "."
X * character. If the token ends on a "." (network number), return YES if
X * it matches the first fields of the string. If the token begins with a
X * "@" (netgroup name), return YES if the string is a (host) member of
X * the netgroup. Return YES if the token fully matches the string. If the
X * token is a netnumber/netmask pair, return YES if the address is a
X * member of the specified subnet.
X */
X
X if (tok[0] == '.') { /* domain: match last fields */
X if ((str_len = strlen(string)) > (tok_len = strlen(tok))
X && strcasecmp(tok, string + str_len - tok_len) == 0)
X return (YES);
X } else if (tok[0] == '@') { /* netgroup: look it up */
X#ifdef NETGROUP
X if (mydomain == 0)
X yp_get_default_domain(&mydomain);
X if (!isdigit(string[0])
X && innetgr(tok + 1, string, (char *) 0, mydomain))
X return (YES);
X#else
X syslog(LOG_ERR, "wrapper: netgroup support is not configured");
X return (NO);
X#endif
X } else if (strcasecmp(tok, "ALL") == 0) { /* all: match any */
X return (YES);
X } else if (strcasecmp(tok, "FAIL") == 0) { /* fail: match any */
X return (FAIL);
X } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
X if (strchr(string, '.') == 0 && strcasecmp(string, "unknown") != 0)
X return (YES);
X } else if (!strcasecmp(tok, string)) { /* match host name or address */
X return (YES);
X } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */
X if (strncmp(tok, string, tok_len) == 0)
X return (YES);
X } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */
X if (isdigit(string[0]) && masked_match(tok, cut, string))
X return (YES);
X }
X return (NO);
X}
X
X/* masked_match - match address against netnumber/netmask */
X
Xstatic int masked_match(tok, slash, string)
Xchar *tok;
Xchar *slash;
Xchar *string;
X{
X unsigned long net;
X unsigned long mask;
X unsigned long addr;
X
X if ((addr = inet_addr(string)) == INADDR_NONE)
X return (NO);
X *slash = 0;
X net = inet_addr(tok);
X *slash = '/';
X if (net == INADDR_NONE || (mask = inet_addr(slash + 1)) == INADDR_NONE) {
X syslog(LOG_ERR, "bad net/mask access control: %s", tok);
X return (NO);
X }
X return ((addr & mask) == net);
X}
X
X/* xgets - fgets() with backslash-newline stripping */
X
Xstatic char *xgets(buf, len, fp)
Xchar *buf;
Xint len;
XFILE *fp;
X{
X int got;
X char *start = buf;
X
X for (;;) {
X if (fgets(buf, len, fp) == 0)
X return (buf > start ? start : 0);
X got = strlen(buf);
X if (got >= 2 && buf[got - 2] == '\\' && buf[got - 1] == '\n') {
X got -= 2;
X buf += got;
X len -= got;
X buf[0] = 0;
X } else {
X return (start);
X }
X }
X}
END_OF_hosts_access.c
if test 11173 -ne `wc -c <hosts_access.c`; then
echo shar: \"hosts_access.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f shell_cmd.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"shell_cmd.c\"
else
echo shar: Extracting \"shell_cmd.c\" \(2883 characters\)
sed "s/^X//" >shell_cmd.c <<'END_OF_shell_cmd.c'
X /*
X * shell_cmd() takes a shell command template and performs %a (host
X * address), %c (client info), %h (host name or address), %d (daemon name),
X * %p (process id) and %u (user name) substitutions. The result is executed
X * by a /bin/sh child process, with standard input, standard output and
X * standard error connected to /dev/null.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) shell_cmd.c 1.3 93/03/07 22:47:39";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <signal.h>
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strncpy();
Xextern void closelog();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Forward declarations. */
X
Xstatic void do_child();
X
X/* shell_cmd - expand %<char> sequences and execute shell command */
X
Xvoid shell_cmd(string, daemon, client)
Xchar *string;
Xchar *daemon;
Xstruct from_host *client;
X{
X char cmd[BUFSIZ];
X int child_pid;
X int wait_pid;
X int daemon_pid = getpid();
X
X /*
X * Most of the work is done within the child process, to minimize the
X * risk of damage to the parent.
X */
X
X switch (child_pid = fork()) {
X case -1: /* error */
X syslog(LOG_ERR, "fork: %m");
X break;
X case 00: /* child */
X percent_x(cmd, sizeof(cmd), string, daemon, client, daemon_pid);
X do_child(daemon, cmd);
X /* NOTREACHED */
X default: /* parent */
X while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
X /* void */ ;
X }
X}
X
X/* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
X
Xstatic void do_child(myname, command)
Xchar *myname;
Xchar *command;
X{
X char *error = 0;
X int tmp_fd;
X
X /*
X * SunOS 4.x may send a SIGHUP to grandchildren if the child exits first.
X * Sessions and process groups make old and grown-up programmers tear out
X * what little hair is left and run away crying.
X */
X
X signal(SIGHUP, SIG_IGN);
X
X /*
X * Close a bunch of file descriptors. The Ultrix inetd only passes stdin,
X * but other inetd implementations set up stdout as well. Ignore errors.
X */
X
X closelog();
X for (tmp_fd = 0; tmp_fd < 10; tmp_fd++)
X (void) close(tmp_fd);
X
X /* Set up new stdin, stdout, stderr, and exec the shell command. */
X
X if (open("/dev/null", 2) != 0) {
X error = "open /dev/null: %m";
X } else if (dup(0) != 1 || dup(0) != 2) {
X error = "dup: %m";
X } else {
X (void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
X error = "execl /bin/sh: %m";
X }
X
X /* We can reach the following code only if there was an error. */
X
X#ifdef LOG_MAIL
X (void) openlog(myname, LOG_PID, FACILITY);
X#else
X (void) openlog(myname, LOG_PID);
X#endif
X syslog(LOG_ERR, error);
X exit(0);
X}
END_OF_shell_cmd.c
if test 2883 -ne `wc -c <shell_cmd.c`; then
echo shar: \"shell_cmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f log_tcp.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"log_tcp.h\"
else
echo shar: Extracting \"log_tcp.h\" \(1448 characters\)
sed "s/^X//" >log_tcp.h <<'END_OF_log_tcp.h'
X/* @(#) log_tcp.h 1.3 93/03/07 22:47:41 */
X
X/* Location of the access control files. */
X
X#ifndef HOSTS_ALLOW
X#define HOSTS_ALLOW "/etc/hosts.allow"
X#endif
X
X#ifndef HOSTS_DENY
X#define HOSTS_DENY "/etc/hosts.deny"
X#endif
X
X /* Structure filled in by the fromhost() routine. */
X
Xstruct from_host {
X int sock_type; /* socket type, see below */
X char *name; /* host name */
X char *addr; /* host address */
X char *user; /* user name */
X struct sockaddr_in *sin; /* their side of the link */
X};
X
X#define FROM_UNKNOWN "unknown" /* name or address lookup failed */
X#define FROM_HOST(f) \
X (((f)->name[0] && strcmp((f)->name, FROM_UNKNOWN)) ? (f)->name : (f)->addr)
X
X#define FROM_ADDRLEN (4*3+3+1) /* string with IP address */
X
X/* Socket types: 0 means unknown. */
X
X#define FROM_CONNECTED 1 /* connection-oriented */
X#define FROM_UNCONNECTED 2 /* non connection-oriented */
X
X/* Global functions. */
X
Xextern int fromhost(); /* get/validate remote host info */
Xextern int hosts_access(); /* access control */
Xextern void refuse(); /* refuse request */
Xextern void shell_cmd(); /* execute shell command */
Xextern void percent_x(); /* do %<char> expansion */
Xextern char *rfc931_name(); /* remote name from RFC 931 daemon */
Xextern char *hosts_info(); /* show origin of connection */
Xextern void clean_exit(); /* clean up and exit */
X
X/* Global variables. */
X
Xextern int log_severity; /* for connection logging */
END_OF_log_tcp.h
if test 1448 -ne `wc -c <log_tcp.h`; then
echo shar: \"log_tcp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f try.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"try.c\"
else
echo shar: Extracting \"try.c\" \(3200 characters\)
sed "s/^X//" >try.c <<'END_OF_try.c'
X /*
X * try - program to try out host access-control tables, including the
X * optional shell commands.
X *
X * usage: try process_name host_name_or_address
X *
X * where process_name is a daemon process name (argv[0] value). If a host name
X * is specified, both the name and address will be used to check the address
X * control tables. If a host address is specified, the program pretends that
X * host name lookup failed.
X *
X * Most errors will be reported to the syslog daemon, so you'd better keep a
X * tail on the logfile.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) try.c 1.3 93/03/07 22:47:43";
X#endif
X
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X
X#ifdef HOSTS_ACCESS
X
X#ifndef INADDR_NONE
X#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
X#endif
X
X#include "log_tcp.h"
X
X#ifdef INET_ADDR_BUG
X#include "inet_addr_fix"
X#endif
X
Xint log_severity = SEVERITY; /* run-time adjustable */
X
X/* Try out a (daemon,client) pair */
X
Xtry(daemon, name, addr)
Xchar *daemon;
Xchar *name;
Xchar *addr;
X{
X printf(" Daemon: %s\n", daemon);
X printf(" Hostname: %s\n", name);
X printf(" Address: %s\n", addr);
X printf(" Access: %s\n",
X hosts_ctl(daemon, name, addr, "you") ? "granted" : "denied");
X}
X
X/* function to intercept the real shell_cmd() */
X
Xvoid shell_cmd(cmd, daemon, client)
Xchar *cmd;
Xchar *daemon;
Xstruct from_host *client;
X{
X char buf[BUFSIZ];
X int pid = getpid();
X
X percent_x(buf, sizeof(buf), cmd, daemon, client, pid);
X printf(" Command: %s\n", buf);
X}
X
X/* function to intercept the real process_options() */
X
Xprocess_options(options, daemon, client)
Xchar *options;
Xchar *daemon;
Xstruct from_host *client;
X{
X char buf[BUFSIZ];
X int pid = getpid();
X
X percent_x(buf, sizeof(buf), options, daemon, client, pid);
X printf(" Options: %s\n", buf);
X}
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X struct hostent *hp;
X
X#ifdef LOG_MAIL
X openlog(argv[0], LOG_PID, FACILITY);
X#else
X openlog(argv[0], LOG_PID);
X#endif
X
X /*
X * Abuse inet_addr() to find out if a host name or address was specified.
X *
X * If a host address is specified, pretend that the host name lookup failed.
X * This allows us to simulate the effect of host name lookup failures.
X *
X * If a host name is specified, insist that the address is known. The reason
X * for giving up is that in real life, a host address is always
X * available.
X */
X
X if (argc != 3) {
X fprintf(stderr, "usage: %s process_name host_name_or_address\n",
X argv[0]);
X return (1);
X }
X if (inet_addr(argv[2]) != INADDR_NONE) { /* address specified */
X try(argv[1], FROM_UNKNOWN, argv[2]);
X return (0);
X }
X if ((hp = gethostbyname(argv[2])) == 0) { /* address lookup fails */
X fprintf(stderr, "host %s: address lookup failed\n", argv[2]);
X return (1);
X }
X while (hp->h_addr_list[0]) /* name and address known */
X try(argv[1], hp->h_name,
X inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
X return (0);
X}
X
X#else
X
Xmain()
X{
X fprintf(stderr, "host access control is not enabled.\n");
X return (1);
X}
X
X#endif
END_OF_try.c
if test 3200 -ne `wc -c <try.c`; then
echo shar: \"try.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f refuse.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"refuse.c\"
else
echo shar: Extracting \"refuse.c\" \(737 characters\)
sed "s/^X//" >refuse.c <<'END_OF_refuse.c'
X /*
X * refuse() reports a refused connection, and takes the consequences: in
X * case of a datagram-oriented service, the unread datagram is taken from
X * the input queue (or inetd would see the same datagram again and again);
X * the program is terminated.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) refuse.c 1.2 92/06/11 22:21:34";
X#endif
X
X/* System libraries. */
X
X#include <syslog.h>
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* refuse - refuse request from bad host */
X
Xvoid refuse(client)
Xstruct from_host *client;
X{
X syslog(LOG_WARNING, "refused connect from %s", hosts_info(client));
X clean_exit(client);
X /* NOTREACHED */
X}
END_OF_refuse.c
if test 737 -ne `wc -c <refuse.c`; then
echo shar: \"refuse.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile.dist -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Makefile.dist\"
else
echo shar: Extracting \"Makefile.dist\" \(15575 characters\)
sed "s/^X//" >Makefile.dist <<'END_OF_Makefile.dist'
X# @(#) Makefile.dist 1.2 93/03/24 22:42:41
X#
X# If you did not already do so, copy the file Makefile.dist to Makefile
X# and edit the copy, not the original. Have a copy of the README file at
X# hand while editing. It gives some additional background.
X#
X# For your convenience, all configurable parameters have been moved into
X# the Makefile, so that you do not have to hack the source files anymore.
X#
X# Some parameters must always be set to match the operating environment.
X# Other parameter settings are a matter of taste. Their sections headings
X# are labeled "(Optional)". The defaults correspond to the programs as
X# documented in the manual pages.
X
X######################################################
X# Choice between easy and advanced installation recipe
X#
X# According to the easy installation recipe in the README file, vendor-
X# provided network daemons are moved to "some other" directory, and the
X# tcpd wrapper fills in the "holes". For this mode of operation, the
X# REAL_DAEMON_DIR macro should be set to the "some other" directory.
X# Uncomment the appropriate line. The "..." is here for historical
X# reasons only; you will probably want to use some other name. Watch out
X# for the quotes and backslashes.
X
XREAL_DAEMON_DIR=\"/usr/etc/...\" # BSD 4.3 Ultrix 4.x SunOS 4.x
X#REAL_DAEMON_DIR=\"/usr/sbin/...\" # SysV.4 Solaris 2.x
X#REAL_DAEMON_DIR=\"/usr/libexec/...\" # BSD 4.4
X
X# According to the advanced installation recipe, vendor-provided daemons
X# are left alone, and the inetd file is edited instead. In that case, the
X# REAL_DAEMON_DIR macro should reflect the actual directory with (most of)
X# your vendor-provided network daemons. Uncomment the appropriate line.
X
X#REAL_DAEMON_DIR=\"/usr/etc\" # BSD 4.3 Ultrix 4.x SunOS 4.x
X#REAL_DAEMON_DIR=\"/usr/sbin\" # SysV.4 Solaris 2.x
X#REAL_DAEMON_DIR=\"/usr/libexec\" # BSD 4.4
X
X#########################################################
X# Differences between ranlib(1) and ar(1) implementations
X#
X# Some C compilers (Ultrix 4.x) insist that ranlib(1) be run on an object
X# library; some don't care as long as the modules are in the right order;
X# some systems don't even have a ranlib(1) command. SGI IRIX uses the 's'
X# option to the 'ar' command instead. Make your choice.
X
XRANLIB = ranlib # have ranlib (BSD-ish UNIX)
X#RANLIB = echo # no ranlib (SYSV-ish UNIX)
X
XARFLAGS = rv # OK for most systems
X#ARFLAGS= rvs # ranlib flag for 'ar' on IRIX 4.0.x
X
X#######################################################
X# Routines that are not present in the system libraries
X#
X# The strcasecmp.c file provided with this package comes from 4.3+BSD
X# UNIX. The setenv.c module is a re-implementation of the 4.4 BSD one.
X# strtok.c comes from 4.4BSD.
X
XAUX_OBJ = setenv.o # no setenv(3)
X#AUX_OBJ= setenv.o strcasecmp.o # no setenv(3) and no strcasecmp(3)
X#AUX_OBJ= setenv.o strcasecmp.o strtok.o
X
X# While building the file strcasecmp.o, the compiler may complain that
X# u_char is undefined. Uncomment the following definition for a fix.
X#
X#UCHAR = -Du_char="unsigned char" # no u_char type
X
X# Uncomment the following if your C library has index/rindex/bcmp
X# but does not provide the strchr/strrchr/memcmp routines. If that
X# is the case, you probably also do not have strtok() (see above).
X#
X#STRINGS= -Dindex=strchr -Drindex=strrchr -Dmemcmp=bcmp
X
X###########################################
X# Selection of non-default object libraries
X#
X# Many System-V versions require that you explicitly specify the networking
X# libraries (for example, -lnet or -linet).
X#
X#LIBS = -lsocket -lnsl # SysV.4 Solaris 2.x
X#LIBS = -lsun # IRIX
X
X#########################
X# Ultrix-specific section
X#
X# Ultrix users may want to use the miscd wrapper, too. The Ultrix miscd
X# implements among others the SYSTAT service which runs the WHO command,
X# and thus provides a subset of the finger service. The very first wrapper
X# application (in the early hours of May 20, 1990) was to monitor SYSTAT.
X
Xall: tcpd try # no Ultrix miscd
X#all: tcpd try miscd # Ultrix, monitor systat etc. too
X
X#REAL_MISCD=\"/usr/etc/.../miscd\" # easy installation
X#REAL_MISCD=\"/usr/etc/miscd\" # advanced installation
X
X################################
X# System-specific compiler flags
X#
X# Apollo Domain/OS offers both bsd and sys5 environments, sometimes
X# on the same machine. If your Apollo is primarily sys5.3 and also
X# has bsd4.3, uncomment the following to build under bsd and run under
X# either environment.
X#
X#SYSTYPE= -A run,any -A sys,any
X
X# For MIPS RISC/os 4_52.p3, uncomment the following definition.
X#
X#SYSTYPE= -sysname bsd43
X
X############################
X# Working around system bugs
X#
X# Some versions of Apollo or SYSV.4 UNIX have a bug in the getpeername(2)
X# routine. You may have this bug when the wrapper reports that all UDP
X# connections come from address 0.0.0.0. Compile with -DGETPEERNAME_BUG
X# for a workaround. The workaround does no harm on other systems. If in
X# doubt, leave it in.
X#
X# Some System V versions (Solaris 2) have a problem in the recvfrom()
X# emulation code. You may have this bug when the wrapper programs
X# complain about "unexpected address family 0" when processing an UDP
X# request. Compile with -DRECVFROM_BUG for a workaround. The workaround
X# does no harm on other systems. If in doubt, leave it in.
X#
X# With some System V implementations (SCO UNIX 3.2v4), even compiling
X# with -DRECVFROM_BUG does not solve the "address family 0" problem. If
X# that is the case, compile with -DADDRESS_FAMILY_BUG instead.
X#
X# DG/UX 5.4.1 comes with an inet_ntoa() function that returns a structure
X# instead of a long integer. Compile with -DINET_ADDR_BUG to work around
X# this mutant behavour.
X
XBUGS = -DGETPEERNAME_BUG -DRECVFROM_BUG # -DADDRESS_FAMILY_BUG
X
X####################################################
X# Whether or not your system has NIS (or YP) support
X#
X# If your system supports NIS or YP-style netgroups, enable the following
X# macro definition. Netgroups are used only for host access control.
X#
X#NETGROUP= -DNETGROUP
X
X# End of the required configuration options; all other ones are optional.
X#########################################################################
X
X################################################################
X# Changing the default disposition of logfile records (Optional)
X#
X# By default, logfile entries are written to the same file as used for
X# sendmail transaction logs. See your /etc/syslog.conf file for actual
X# path names of logfiles. The tutorial section in the README file
X# gives a brief introduction to the syslog daemon.
X#
X# Change the FACILITY definition below if you disagree with the default
X# disposition. Some syslog versions (including Ultrix 4.x) do not provide
X# this flexibility.
X#
X# If nothing shows up on your system, it may be that the syslog records
X# are sent to a dedicated loghost. It may also be that no syslog daemon
X# is running at all. The README file gives pointers to surrogate syslog
X# implementations for systems that have no syslog library routines or
X# no syslog daemons.
X#
X# The LOG_XXX names below are taken from the /usr/include/syslog.h file.
X
XFACILITY= LOG_MAIL # LOG_MAIL is what most sendmail daemons use
X
X# The syslog priority at which successful connections are logged.
X
XSEVERITY= LOG_INFO # LOG_INFO is normally not logged to the console
X
X#############################################
X# Enabling remote username lookups (Optional)
X#
X# By default, the wrappers just report the remote host name (the host
X# address if the host name lookup fails or times out). Username lookups
X# require that the remote host runs a daemon that supports a RFC 931 like
X# protocol. Remote user name lookups are not possible for UDP-based
X# connections, and can cause noticeable delays with connections from
X# non-UNIX PCs. On some systems, remote username lookups can trigger a
X# kernel bug, causing loss of service. The README file gives details on
X# how to find out if your system has that problem.
X#
X# Uncomment the following definition if the wrappers should always
X# attempt to get the remote user name.
X#
X# The default username lookup timeout is 30 seconds.
X#
X#AUTH = -DRFC931_TIMEOUT=30 -DRFC931
X
X# The USER_AT_HOST feature does selective username lookups. It triggers
X# on access control patterns of the form xxx@yyy. Until now, such
X# patterns were not used, so that USER_AT_HOST does not break existing
X# rules.
X#
X# The feature is not documented and is not yet intended for general use,
X# because it can complicate the design of access control tables.
X#
X# With USER_AT_HOST enabled, remote username lookups are done only for
X# user_pattern@host_pattern expressions in the access control files, but
X# only when the host_pattern matches. Example: "ALL: @pcgroup ALL@ALL"
X# avoids user name lookups for members of the pcgroup netgroup. The
X# user_pattern syntax is identical to that of host_pattern, but "ALL"
X# is usually the only user_pattern that makes sense.
X#
X# The default username lookup timeout is 30 seconds.
X#
X#AUTH = -DRFC931_TIMEOUT=30 -DUSER_AT_HOST
X
X########################################################
X# Turning on experimental language extensions (Optional)
X#
X# Instead of the officially documented access control language, the
X# software can be configured to implement a more experimental language
X# that is easily extended. The experimental language is implemented by
X# the "options.c" source module which also serves as its documentation.
X
XSTYLE = -DOPTIONS_STYLE=shell_cmd # The documented language
X#STYLE = -DOPTIONS_STYLE=process_options # The experimental one
X
X######################################################
X# Changing the default file protection mask (Optional)
X#
X# On many systems, network daemons and other system processes are started
X# with a zero umask value, so that world-writable files may be produced.
X# It is a good idea to edit your /etc/rc* files so that they begin with
X# an explicit umask setting. On our site we use `umask 022' because it
X# does not break anything yet gives adequate protection against tampering.
X#
X# The following macro specifies the default umask for processes run under
X# control of the daemon wrappers. Comment it out only if you are certain
X# that inetd and its children are started with a safe umask value.
X
XUMASK = -DDAEMON_UMASK=022
X
X#######################################
X# Turning off access control (Optional)
X#
X# By default, host access control is enabled. To disable host access
X# control, comment out the following definition. Host access control
X# can also be turned off at runtime by providing no or empty access
X# control tables.
X
XACCESS = -DHOSTS_ACCESS
X
X########################################################
X# Changing the access control table pathnames (Optional)
X#
X# The HOSTS_ALLOW and HOSTS_DENY macros define where the programs will
X# look for access control information. Watch out for the quotes and
X# backslashes when you make changes.
X
XTABLES = -DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\"
X
X###########################################
X# Turning off host NAME checking (Optional)
X#
X# By default, the software tries to protect against hosts that claim to
X# have someone elses host name. This is relevant for network services
X# whose authentication depends on host names, such as rsh and rlogin.
X#
X# With paranoid mode on, connections will be rejected when the host name
X# does not match the host address. Connections will also be rejected when
X# the host name cannot be verified because gethostbyname() fails.
X#
X# Comment out the following definition if you do not need this additional
X# protection. If paranoid mode is off, and a host name check fails, the
X# daemon wrappers will use only the host address, but your daemons may
X# still use the host name.
X
XPARANOID= -DPARANOID
X
X#############################################
X# Turning on host ADDRESS checking (Optional)
X#
X# Optionally, the software tries to protect against hosts that pretend to
X# have someone elses host address. This is relevant for network services
X# whose authentication depends on host names, such as rsh and rlogin,
X# because the network address is used to look up the remote host name.
X#
X# The protection is effective only when the offending host claims to have
X# a network address that lies outside its own network.
X#
X# My site has been running rlogind and rshd daemons that implement this
X# feature for more than 2 years, and without any ill effects.
X#
X# This feature cannot be used with SunOS 4.x because of a kernel bug in
X# the implementation of the getsockopt() system call. Kernel panics have
X# been reported for SunOS 4.1.1 and SunOS 4.1.2. Symptoms are "BAD TRAP"
X# and "Data fault" while executing the tcp_ctloutput() kernel function.
X#
X# Uncomment the following macro definition if your getsockopt() is OK.
X#
X# KILL_OPT= -DKILL_IP_OPTIONS
X
X## End configuration options
X############################
X
XCFLAGS = -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
X $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) -DREAL_MISCD=$(REAL_MISCD) \
X -DREAL_DAEMON_DIR=$(REAL_DAEMON_DIR) $(STYLE) $(KILL_OPT) \
X -DSEVERITY=$(SEVERITY) $(UCHAR) $(TABLES) $(STRINGS)
X
XLIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o hosts_info.o \
X hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
X fromhost.o fix_options.o
X
XKIT = README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
X log_tcp.h try.c refuse.c Makefile.dist hosts_access.5 strcasecmp.c \
X BLURB rfc931.c tcpd.8 hosts_info.c hosts_access.3 hosts_ctl.c \
X percent_x.c options.c clean_exit.c setenv.c patchlevel.h strtok.c \
X fix_options.c inet_addr_fix
X
XLIB = libwrap.a
X
X$(LIB): $(LIB_OBJ)
X rm -f $(LIB)
X ar $(ARFLAGS) $(LIB) $(LIB_OBJ)
X $(RANLIB) $(LIB)
X
Xtcpd: tcpd.o fromhost.o $(LIB)
X $(CC) $(CFLAGS) -o $@ tcpd.o fromhost.o $(LIB) $(LIBS)
X
Xmiscd: miscd.o fromhost.o $(LIB)
X $(CC) $(CFLAGS) -o $@ miscd.o fromhost.o $(LIB) $(LIBS)
X
Xtry: try.o $(LIB)
X $(CC) $(CFLAGS) -o $@ try.o $(LIB) $(LIBS)
X
Xfromhost: fromhost.c log_tcp.h Makefile $(LIB)
X $(CC) $(CFLAGS) -DTEST -o fromhost fromhost.c $(LIB) $(LIBS)
X rm -f fromhost.o
X
Xshar: $(KIT)
X @shar $(KIT)
X
Xkit: $(KIT)
X @makekit $(KIT)
X
Xarchive:
X $(ARCHIVE) $(KIT)
X
Xclean:
X rm -f tcpd miscd try fromhost *.[oa] core
X
X# Enable all bells and whistles for linting.
X
Xlint: tcpd_lint miscd_lint try_lint
X
Xtcpd_lint:
X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
X -DGETPEERNAME_BUG -DDAEMON_UMASK=022 -DSEVERITY=$(SEVERITY) \
X -DUSER_AT_HOST -DKILL_IP_OPTIONS -DOPTIONS_STYLE=process_options \
X tcpd.c fromhost.c hosts_access.c shell_cmd.c refuse.c rfc931.c \
X hosts_info.c percent_x.c clean_exit.c options.c setenv.c fix_options.c
X
Xmiscd_lint:
X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
X -DGETPEERNAME_BUG -DDAEMON_UMASK=022 -DSEVERITY=$(SEVERITY) \
X -DUSER_AT_HOST -DKILL_IP_OPTIONS -DOPTIONS_STYLE=process_options \
X miscd.c fromhost.c hosts_access.c shell_cmd.c refuse.c rfc931.c \
X hosts_info.c percent_x.c clean_exit.c options.c setenv.c fix_options.c
X
Xtry_lint:
X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DNETGROUP try.c \
X hosts_ctl.c hosts_access.c hosts_info.c percent_x.c
X
X# Compilation dependencies.
X
Xclean_exit.o: log_tcp.h Makefile
Xfix_options.o: log_tcp.h Makefile
Xfromhost.o: log_tcp.h Makefile
Xhosts_access.o: log_tcp.h Makefile
Xhosts_ctl.o: log_tcp.h Makefile
Xhosts_info.o: log_tcp.h Makefile
Xmiscd.o: patchlevel.h log_tcp.h Makefile
Xoptions.o: log_tcp.h Makefile
Xpercent_x.o: log_tcp.h Makefile
Xrefuse.o: log_tcp.h Makefile
Xrfc931.o: log_tcp.h Makefile
Xshell_cmd.o: log_tcp.h Makefile
Xtcpd.o: patchlevel.h log_tcp.h Makefile
Xtry.o: log_tcp.h Makefile
END_OF_Makefile.dist
if test 15575 -ne `wc -c <Makefile.dist`; then
echo shar: \"Makefile.dist\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.5 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"hosts_access.5\"
else
echo shar: Extracting \"hosts_access.5\" \(9533 characters\)
sed "s/^X//" >hosts_access.5 <<'END_OF_hosts_access.5'
X.TH HOSTS_ACCESS 5
X.SH NAME
Xhosts_access \- format of host access control files
X.SH DESCRIPTION
XThis manual page describes a simple access control language that is
Xbased on client (host name or address) and server (process name)
Xpatterns. Examples are given at the end. The impatient reader can skip
Xto the EXAMPLES section for a quick introduction.
X.PP
XIn the following text, \fIdaemon\fR is the the process name of a
Xnetwork daemon process, and \fIclient\fR is the name and/or address of
Xa host requesting service. Network daemon process names are specified
Xin the inetd configuration file.
X.SH ACCESS CONTROL FILES
XThe access control software consults two files:
X.IP o
XAccess will be granted when a (daemon,client) pair matches an entry in
Xthe \fI/etc/hosts.allow\fR file.
X.IP o
XOtherwise, access will be denied when a (daemon,client) pair matches an
Xentry in the \fI/etc/hosts.deny\fR file.
X.IP o
XOtherwise, access will be granted.
X.PP
XA non-existing access control file is treated as if it were an empty
Xfile. Thus, access control can be turned off by providing no access
Xcontrol files.
X.SH ACCESS CONTROL RULES
XEach access control file consists of zero or more lines of text. These
Xlines are processed in order of appearance. The search terminates when a
Xmatch is found.
X.IP o
XA newline character is ignored when it is preceded by a backslash
Xcharacter.
X.IP o
XBlank lines or lines that begin with a `#\' character are ignored.
X.IP o
XAll other lines should satisfy the following format, things between []
Xbeing optional:
X.sp
X.ti +3
Xdaemon_list : client_list [ : shell_command ]
X.PP
X\fIdaemon_list\fR is a list of one or more daemon process names
X(argv[0] values) or wildcards (see below).
X.PP
X\fIclient_list\fR is a list
Xof one or more host names, host addresses, patterns or wildcards (see
Xbelow) that will be matched against the remote host name or address.
X.PP
XList elements should be separated by blanks and/or commas.
X.PP
XWith the exception of NIS (YP) netgroup lookups, all access control
Xchecks are case insensitive.
X.br
X.ne 4
X.SH PATTERNS
XThe access control language implements the following patterns:
X.IP o
XA string that begins with a `.\' character. A client name or address
Xis matched if its last components match the specified pattern. For
Xexample, the pattern `.tue.nl\' matches the host name
X`wzv.win.tue.nl\'.
X.IP o
XA string that ends with a `.\' character. A client name or address is
Xmatched if its first fields match the given string. For example, the
Xpattern `131.155.\' matches the address of (almost) every host on the
XEind\%hoven University network (131.155.x.x).
X.IP o
XA string that begins with a `@\' character is treated as a netgroup
Xname. Netgroups are usually supported on systems with NIS (formerly
XYP) data bases. A client host name is matched if it is a (host) member
Xof the specified netgroup.
X.IP o
XAn expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
X`net/mask\' pair. A client address is matched if `net\' is equal to the
Xbitwise AND of the address and the `mask\'. For example, the net/mask
Xpattern `131.155.72.0/255.255.254.0\' matches every address in the
Xrange `131.155.72.0\' through `131.155.73.255\'.
X.SH WILDCARDS
XThe access control language supports explicit wildcards:
X.IP ALL
XIf this token appears in a daemon_list, it matches all network daemon
Xprocess names. If the ALL token appears in a client_list, it matches
Xall client names and addresses.
X.IP LOCAL
XMatches any string that does not contain a dot character.
XTypical use is in client_lists.
X.IP UNKNOWN
XMatches any host whose name and/or address lookup failed. Should be
Xused with care, because host names may also be unavailable due to
Xtemporary name server problems.
X.IP FAIL
XLike the ALL wildcard, but causes the software to pretend that the scan
Xof the current access control table fails. FAIL is being phased out; it
Xwill become an undocumented feature. The EXCEPT operator (see below) is
Xa much cleaner alternative.
X.br
X.ne 6
X.SH OPERATORS
X.IP EXCEPT
XIntended use is of the form: `list_1 EXCEPT list_2\'; this construct
Xmatches anything that matches \fIlist_1\fR unless it matches
X\fIlist_2\fR. This construct can be used in daemon_lists and in
Xclient_lists. The EXCEPT operator can be nested and is
Xright-associative (just like C's assignment operator).
X.br
X.ne 6
X.SH SHELL COMMANDS
XIf the first-matched access control rule contains a shell command, that
Xcommand is subjected to the following substitutions:
X.IP %a
Xexpands to the remote host address.
X.IP %c
Xexpands to client information: user@host, user@address, a host name, or
Xjust an address, depending on how much information is available.
X.IP %h
Xexpands to the remote host name (or address, if the host name is
Xunavailable).
X.IP %d
Xexpands to the daemon process name (argv[0] value).
X.IP %p
Xexpands to the daemon process id.
X.IP %u
Xexpands to the remote user name (or "unknown").
X.IP %%
Xexpands to a single `%\' character.
X.PP
XCharacters in % expansions that may confuse the shell are replaced by
Xunderscores.
XThe result is executed by a \fI/bin/sh\fR child process with standard
Xinput, output and error connected to \fI/dev/null\fR. Specify an `&\'
Xat the end of the command if you do not want to wait until it has
Xcompleted.
X.PP
XShell commands should not rely on the PATH setting of the inetd.
XInstead, they should use absolute path names, or they should begin with
Xan explicit PATH=whatever statement.
X.SH EXAMPLES
XThe language is flexible enough that different types of access control
Xpolicy can be expressed with a minimum of fuss. Although the language
Xuses two access control tables, the most common policies can be
Ximplemented with one of the tables being trivial or even empty.
X.PP
XWhen reading the examples below it is important to realize that the
Xallow table is scanned before the deny table, that the search
Xterminates when a match is found, and that access is granted when no
Xmatch is found at all.
X.PP
XThe examples use host and domain names. They can be improved by
Xincluding address and/or network/netmask information, to reduce the
Ximpact of temporary name server lookup failures.
X.SH MOSTLY CLOSED
XIn this case, access is denied by default. Only explicitly authorized
Xhosts are permitted access.
X.PP
XThe default policy (no access) is implemented with a trivial deny
Xfile:
X.PP
X.ne 2
X/etc/hosts.deny:
X.in +3
XALL: ALL
X.PP
XThis denies all service to all hosts, unless they are permitted access
Xby entries in the allow file.
X.PP
XThe explicitly authorized hosts are listed in the allow file.
XFor example:
X.PP
X.ne 2
X/etc/hosts.allow:
X.in +3
XALL: LOCAL @some_netgroup
X.br
XALL: .foobar.edu EXCEPT terminalserver.foobar.edu
X.PP
XThe first rule permits access to all services from hosts in the local
Xdomain (no `.\' in the host name) and from members of the
X\fIsome_netgroup\fP netgroup. The second rule permits access to all
Xservices from all hosts in the \fI.foobar.edu\fP domain, with the
Xexception of \fIterminalserver.foobar.edu\fP.
X.SH MOSTLY OPEN
XHere, access is granted by default; only explicitly specified hosts are
Xrefused service.
X.PP
XThe default policy (access granted) makes the allow file redundant so
Xthat it can be omitted. The explicitly non-authorized hosts are listed
Xin the deny file. For example:
X.PP
X/etc/hosts.deny:
X.in +3
XALL: some.host.name, .some.domain
X.br
XALL EXCEPT in.fingerd: other.host.name, .other.domain
X.PP
XThe first rule denies some hosts all services; the second rule still
Xpermits finger requests from other hosts.
X.SH BOOBY TRAPS
XThe next example permits tftp requests from hosts in the local domain.
XRequests from any other hosts are denied. Instead of the requested
Xfile, a finger probe is sent to the offending host. The result is
Xmailed to the superuser.
X.PP
X.ne 2
X/etc/hosts.allow:
X.in +3
X.nf
Xin.tftpd: LOCAL, .my.domain
X.PP
X.ne 2
X/etc/hosts.deny:
X.in +3
X.nf
Xin.tftpd: ALL: (/usr/ucb/finger -l @%h | /usr/ucb/mail -s %d-%h root) &
X.fi
X.PP
XThe expansion of the %h (remote host) and %d (service name) sequences
Xis described in the section on shell commands.
X.PP
XWarning: do not booby-trap your finger daemon, unless you are prepared
Xfor infinite finger loops.
X.PP
XOn network firewall systems this trick can be carried even further.
XThe typical network firewall only provides a limited set of services to
Xthe outer world. All other services can be "bugged" just like the above
Xtftp example. The result is an excellent early-warning system.
X.br
X.ne 4
X.SH DIAGNOSTICS
XAn error is reported when a syntax error is found in a host access
Xcontrol rule; when the length of an access control rule exceeds the
Xcapacity of an internal buffer; when an access control rule is not
Xterminated by a newline character; when the result of %<character>
Xexpansion would overflow an internal buffer; when a system call fails
Xthat shouldn\'t. All problems are reported via the syslog daemon.
X.SH FILES
X.na
X.nf
X/etc/hosts.allow, (daemon,client) pairs that are granted access.
X/etc/hosts.deny, (daemon,client) pairs that are denied access.
X.ad
X.fi
X.SH SEE ALSO
Xtcpd(8) tcp/ip daemon wrapper program.
X.SH BUGS
XIf a name server lookup times out, the host name will not be available
Xto the access control software, even though the host is registered.
X.PP
XDomain name server lookups are case insensitive; NIS (formerly YP)
Xnetgroup lookups are case sensitive.
X.SH AUTHOR
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl)
XDepartment of Mathematics and Computing Science
XEindhoven University of Technology
XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X\" @(#) hosts_access.5 1.11 93/03/07 22:47:47
END_OF_hosts_access.5
if test 9533 -ne `wc -c <hosts_access.5`; then
echo shar: \"hosts_access.5\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f strcasecmp.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"strcasecmp.c\"
else
echo shar: Extracting \"strcasecmp.c\" \(3767 characters\)
sed "s/^X//" >strcasecmp.c <<'END_OF_strcasecmp.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley. The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strcasecmp.c 5.6 (Berkeley) 6/27/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X
X/*
X * This array is designed for mapping upper and lower case letter
X * together for a case independent comparison. The mappings are
X * based upon ascii character sequences.
X */
Xstatic u_char charmap[] = {
X '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
X '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
X '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
X '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
X '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
X '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
X '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
X '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
X '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
X '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
X '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
X '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
X '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
X '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
X '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
X '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
X '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
X '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
X '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
X '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
X};
X
Xstrcasecmp(s1, s2)
X char *s1, *s2;
X{
X register u_char *cm = charmap,
X *us1 = (u_char *)s1,
X *us2 = (u_char *)s2;
X
X while (cm[*us1] == cm[*us2++])
X if (*us1++ == '\0')
X return(0);
X return(cm[*us1] - cm[*--us2]);
X}
X
Xstrncasecmp(s1, s2, n)
X char *s1, *s2;
X register int n;
X{
X register u_char *cm = charmap,
X *us1 = (u_char *)s1,
X *us2 = (u_char *)s2;
X
X while (--n >= 0 && cm[*us1] == cm[*us2++])
X if (*us1++ == '\0')
X return(0);
X return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
X}
END_OF_strcasecmp.c
if test 3767 -ne `wc -c <strcasecmp.c`; then
echo shar: \"strcasecmp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f BLURB -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"BLURB\"
else
echo shar: Extracting \"BLURB\" \(2068 characters\)
sed "s/^X//" >BLURB <<'END_OF_BLURB'
X@(#) BLURB 1.8 93/03/24 22:42:37
X
XWith the programs that come with this kit you can monitor incoming
Xrequests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
XFINGER, SYSTAT, and many others.
X
XOptional features are: access control based on pattern matching; remote
Xusername lookup using the RFC 931 protocol; protection against attacks
Xfrom hosts that pretend to have someone elses name; protection against
Xattacks from hosts that pretend to have someone elses network address.
X
XThe programs can be installed without requiring any changes to existing
Xsoftware or configuration files. By default, they just log the remote
Xhost name and do some sanity checks on the origin the request. No
Xinformation is exchanged with the remote client process.
X
XThe most notable differences with respect to the previous release are:
X
X - Optional protection against attacks from hosts that pretend to
X have someone elses network address. For example, the address of a
X trusted host within your own network.
X
X - The access control language has been extended with a simple but
X powerful operator that greatly simplifies the design of rule sets
X (ALL: .foo.edu EXCEPT dialup.foo.edu). Blank lines are permitted,
X and long lines can be continued with backslash-newline.
X
X - All configurable stuff, including path names, has been moved into
X the Makefile so that you no longer have to hack source code to just
X configure the programs.
X
X - Ported to Solaris 2. TLI-based applications not yet supported.
X Several workarounds for System V bugs.
X
X - A small loophole in the netgroup lookup code was closed, and the
X remote username lookup code was made more portable.
X
X - Still more documentation. The README file now provides tutorial
X sections with introductions to client, server, inetd and syslogd.
X
XThe default mode of operation should be backwards compatible with
Xearlier versions.
X
X Wietse Venema (wietse@wzv.win.tue.nl),
X Department of Mathematics and Computing Science,
X Eindhoven University of Technology,
X The Netherlands.
END_OF_BLURB
if test 2068 -ne `wc -c <BLURB`; then
echo shar: \"BLURB\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rfc931.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"rfc931.c\"
else
echo shar: Extracting \"rfc931.c\" \(3825 characters\)
sed "s/^X//" >rfc931.c <<'END_OF_rfc931.c'
X /*
X * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
X * protocols. It consults an RFC 931 etc. compatible daemon on the client
X * host to look up the remote user name. The information should not be used
X * for authentication purposes.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X *
X * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
X * Bernstein (brnstnd@kramden.acf.nyu.edu).
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) rfc931.c 1.4 93/03/07 22:47:52";
X#endif
X
X#include <stdio.h>
X#include <syslog.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <setjmp.h>
X#include <signal.h>
X
X#include "log_tcp.h"
X
X#define RFC931_PORT 113 /* Semi-well-known port */
X
X#ifndef RFC931_TIMEOUT
X#define RFC931_TIMEOUT 30 /* wait for at most 30 seconds */
X#endif
X
Xextern char *strchr();
Xextern char *inet_ntoa();
X
Xstatic jmp_buf timebuf;
X
X/* timeout - handle timeouts */
X
Xstatic void timeout(sig)
Xint sig;
X{
X longjmp(timebuf, sig);
X}
X
X/* rfc931_name - return remote user name */
X
Xchar *rfc931_name(there)
Xstruct sockaddr_in *there; /* remote link information */
X{
X struct sockaddr_in here; /* local link information */
X struct sockaddr_in sin; /* for talking to RFC931 daemon */
X int length;
X int s;
X unsigned remote;
X unsigned local;
X static char user[256]; /* XXX */
X char buffer[512]; /* YYY */
X FILE *fp;
X char *cp;
X char *result = FROM_UNKNOWN;
X
X /* Find out local address and port number of stdin. */
X
X length = sizeof(here);
X if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
X syslog(LOG_ERR, "getsockname: %m");
X return (result);
X }
X
X /*
X * The socket that will be used for user name lookups should be bound to
X * the same local IP address as stdin. This will automagically happen on
X * hosts that have only one IP network address. When the local host has
X * more than one IP network address, we must do an explicit bind() call.
X */
X
X if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
X return (result);
X
X sin = here;
X sin.sin_port = 0;
X if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) {
X syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr));
X return (result);
X }
X /* Set up timer so we won't get stuck. */
X
X signal(SIGALRM, timeout);
X if (setjmp(timebuf)) {
X close(s); /* not: fclose(fp) */
X return (result);
X }
X alarm(RFC931_TIMEOUT);
X
X /* Connect to the RFC931 daemon. */
X
X sin = *there;
X sin.sin_port = htons(RFC931_PORT);
X if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
X || (fp = fdopen(s, "w+")) == 0) {
X close(s);
X alarm(0);
X return (result);
X }
X
X /*
X * Use unbuffered I/O or we may read back our own query. setbuf() must be
X * called before doing any I/O on the stream. Thanks for the reminder,
X * Paul Kranenburg <pk@cs.few.eur.nl>!
X */
X
X setbuf(fp, (char *) 0);
X
X /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
X
X fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
X fflush(fp);
X
X /*
X * Read response from server. Use fgets()/sscanf() instead of fscanf()
X * because there is no buffer for pushback. Thanks, Chris Turbeville
X * <turbo@cse.uta.edu>.
X */
X
X if (fgets(buffer, sizeof(buffer), fp) != 0
X && ferror(fp) == 0 && feof(fp) == 0
X && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
X &remote, &local, user) == 3
X && ntohs(there->sin_port) == remote
X && ntohs(here.sin_port) == local) {
X /* Strip trailing carriage return. */
X
X if (cp = strchr(user, '\r'))
X *cp = 0;
X result = user;
X }
X alarm(0);
X fclose(fp);
X return (result);
X}
END_OF_rfc931.c
if test 3825 -ne `wc -c <rfc931.c`; then
echo shar: \"rfc931.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tcpd.8 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"tcpd.8\"
else
echo shar: Extracting \"tcpd.8\" \(6757 characters\)
sed "s/^X//" >tcpd.8 <<'END_OF_tcpd.8'
X.TH TCPD 8
X.SH NAME
Xtcpd \- access control facility for internet services
X.SH DESCRIPTION
X.PP
XThe \fItcpd\fR program can be set up to monitor incoming requests for
X\fItelnet\fR, \fIfinger\fR, \fIftp\fR, \fIexec\fR, \fIrsh\fR,
X\fIrlogin\fR, \fItftp\fR, \fItalk\fR, \fIcomsat\fR and other services
Xthat have a one-to-one mapping onto executable files.
X.PP
XOperation is as follows: whenever a request for internet service
Xarrives, the \fIinetd\fP daemon is tricked into running the \fItcpd\fP
Xprogram instead of the desired server. \fItcpd\fP logs the request and
Xdoes some additional checks. When all is well, \fItcpd\fP runs the
Xappropriate server program and goes away.
X.PP
XOptional features are: pattern-based access control, patterns, remote
Xusername lookups with the RFC 931 protocol, protection against hosts
Xthat pretend to have someone elses host name, and protection against
Xhosts that pretend to have someone elses network address.
X.SH LOGGING
XConnections that are monitored by
X.I tcpd
Xare reported through the \fIsyslog\fR(3) facility. Each record contains
Xa time stamp, the remote host name and the name of the service
Xrequested. The information can be useful to detect unwanted activities,
Xespecially when logfile information from several hosts is merged.
X.PP
XIn order to find out where your logs are going, examine the syslog
Xconfiguration file, usually /etc/syslog.conf.
X.SH ACCESS CONTROL
XOptionally,
X.I tcpd
Xsupports a simple form of access control that is based on pattern
Xmatching. The access-control software provides hooks for the execution
Xof shell commands when a pattern fires. For details, see the
X\fIhosts_access\fR(5) manual page.
X.SH HOST NAME VERIFICATION
XThe authentication scheme of some protocols (\fIrlogin, rsh\fR) relies
Xon host names. Some implementations believe the host name that they get
Xfrom any random name server; other implementations are more careful but
Xuse a flawed algorithm.
X.PP
X.I tcpd
Xverifies the remote host name that is returned by the address->name DNS
Xserver by looking at the host name and address that are returned by the
Xname->address DNS server. If any discrepancy is detected,
X.I tcpd
Xconcludes that it is dealing with a host that pretends to have someone
Xelses host name.
X.PP
XIf the sources are compiled with the \*QPARANOID\*U option,
X.I tcpd
Xwill drop the connection in case of a host name/address mismatch.
XOtherwise,
X.I tcpd
Xjust pretends that host name lookup failed when logging the connection
Xand consulting the optional access control tables.
X.SH HOST ADDRESS SPOOFING
XBy default,
X.I tcpd
Xdisables source-routing socket options on every connection that it
Xdeals with. This will take care of most attacks from hosts that pretend
Xto have an address that belongs to someone elses network. UDP services
Xdo not benefit from this protection.
X.SH RFC 931
XWhen RFC 931 lookups are enabled (compile-time option) \fItcpd\fR will
Xattempt to establish the name of the remote user. This will succeed
Xonly if the client host runs an RFC 931-compliant daemon. Remote user
Xname lookups will not work for datagram-oriented connections, and may
Xcause noticeable delays in the case of connections from PCs.
X.SH EXAMPLES
XThe details of using \fItcpd\fR depend on pathname information that was
Xcompiled into the program.
X.SH EXAMPLE 1
XThis example applies when \fItcpd\fR expects that the original network
Xdaemons will be moved to a "secret" place.
X.PP
XIn order to monitor access to the \fIfinger\fR service, move the
Xoriginal finger daemon to the "secret" place and install tcpd in the
Xplace of the original finger daemon. No changes are required to
Xconfiguration files.
X.nf
X.sp
X.in +5
X# mkdir /secret/place
X# mv /usr/etc/in.fingerd /secret/place
X# cp tcpd /usr/etc/in.fingerd
X.fi
X.PP
XThe example assumes that the network daemons live in /usr/etc. On some
Xsystems, network daemons live in /usr/sbin or in /usr/libexec, or have
Xno `in.\' prefix to their name.
X.SH EXAMPLE 2
XThis example applies when \fItcpd\fR expects that the network daemons
Xare left in their original place.
X.PP
XIn order to monitor access to the \fIfinger\fR service, perform the
Xfollowing edits on the \fIinetd\fR configuration file (usually
X\fI/etc/inetd.conf\fR or \fI/etc/inet/inetd.conf\fR):
X.nf
X.sp
X.ti +5
Xfinger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
X.sp
Xbecomes:
X.sp
X.ti +5
Xfinger stream tcp nowait nobody /some/where/tcpd in.fingerd
X.sp
X.fi
X.PP
XThe example assumes that the network daemons live in /usr/etc. On some
Xsystems, network daemons live in /usr/sbin or in /usr/libexec, the
Xdaemons have no `in.\' prefix to their name, or there is no userid
Xfield in the inetd configuration file.
X.PP
XSimilar changes will be needed for the other services that are to be
Xcovered by \fItcpd\fR. Send a `kill -HUP\' to the \fIinetd\fR(8)
Xprocess to make the changes effective.
X.SH EXAMPLE 3
XIn the case of daemons that do not live in a common directory ("secret"
Xor otherwise), edit the \fIinetd\fR configuration file so that it
Xspecifies an absolute path name for the process name field. For example:
X.nf
X.sp
X ntalk dgram udp wait root /some/where/tcpd /usr/local/lib/ntalkd
X.sp
X.fi
X.PP
XOnly the last component (ntalkd) of the process name will be used for
Xaccess control and logging.
X.SH BUGS
XSome UDP (and RPC) daemons linger around for a while after they have
Xfinished their work, in case another request comes in. In the inetd
Xconfiguration file these services are registered with the \fIwait\fR
Xoption. Only the request that started such a daemon will be logged.
X.PP
XThe program does not work with RPC services over TCP. These services
Xare registered as \fIrpc/tcp\fR in the inetd configuration file. The
Xonly non-trivial service that is affected by this limitation is
X\fIrexd\fR, which is used by the \fIon(1)\fR command. This is no great
Xloss. On most systems, \fIrexd\fR is less secure than a wildcard in
X/etc/hosts.equiv.
X.PP
XRPC broadcast requests (for example: \fIrwall, rup, rusers\fR) always
Xappear to come from the responding host. What happens is that the
Xclient broadcasts the request to all \fIportmap\fR daemons on its
Xnetwork; each \fIportmap\fR daemon forwards the request to a local
Xdaemon. As far as the \fIrwall\fR etc. daemons know, the request comes
Xfrom the local host.
X.SH FILES
X.PP
XThe default locations of the host access control tables are:
X.PP
X/etc/hosts.allow
X.br
X/etc/hosts.deny
X.SH SEE ALSO
X.na
X.nf
Xhosts_access(5), format of the tcpd access control tables.
Xsyslog.conf(5), format of the syslogd control file.
Xinetd.conf(5), format of the inetd control file.
X.SH AUTHORS
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl),
XDepartment of Mathematics and Computing Science,
XEindhoven University of Technology,
XThe Netherlands.
X\" @(#) tcpd.8 1.2 93/03/07 22:47:54
END_OF_tcpd.8
if test 6757 -ne `wc -c <tcpd.8`; then
echo shar: \"tcpd.8\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_info.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"hosts_info.c\"
else
echo shar: Extracting \"hosts_info.c\" \(788 characters\)
sed "s/^X//" >hosts_info.c <<'END_OF_hosts_info.c'
X /*
X * hosts_info() returns a string with as much information about the origin
X * of a connection as we have: the user name, if known, and the host name,
X * or the host address if the name is not available.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_info.c 1.1 92/06/11 22:21:44";
X#endif
X
X#include <stdio.h>
X
X#include "log_tcp.h"
X
X/* hosts_info - return string with as much about the client as we know */
X
Xchar *hosts_info(client)
Xstruct from_host *client;
X{
X static char buf[BUFSIZ]; /* XXX */
X
X if (client->user[0] && strcmp(client->user, FROM_UNKNOWN)) {
X sprintf(buf, "%s@%s", client->user, FROM_HOST(client));
X return (buf);
X } else {
X return (FROM_HOST(client));
X }
X}
END_OF_hosts_info.c
if test 788 -ne `wc -c <hosts_info.c`; then
echo shar: \"hosts_info.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.3 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"hosts_access.3\"
else
echo shar: Extracting \"hosts_access.3\" \(2018 characters\)
sed "s/^X//" >hosts_access.3 <<'END_OF_hosts_access.3'
X.TH HOSTS_ACCESS 3
X.SH
Xhosts_access, hosts_ctl \- access control library
X.SH SYNOPSIS
X.nf
X#include "log_tcp.h"
X
Xint hosts_access(daemon, client)
Xchar *daemon;
Xstruct from_host *client;
X
Xint hosts_ctl(daemon, client_name, client_addr, client_user)
Xchar *daemon;
Xchar *client_host;
Xchar *client_addr;
Xchar *client_user;
X.fi
X.SH DESCRIPTION
XThe routines described in this document are part of the \fIlibwrap.a\fR
Xlibrary. They implement a pattern-based access control language with
Xoptional shell commands that are executed when a pattern fires.
X.PP
XIn all cases, the daemon argument should specify a daemon process name
X(argv[0] value). The client host address should be a valid address, or
XFROM_UNKNOWN if address lookup failed. The client host name and user
Xname should be empty strings if no information is available,
XFROM_UNKNOWN if lookup failed, or an actual host or user name.
X.PP
Xhosts_access() consults the access control tables described in the
X\fIhosts_access(5)\fR manual page. If a match is found, an optional
Xshell command is executed and the search terminates. hosts_access()
Xreturns zero if access should be denied.
X.PP
Xhosts_ctl() is a wrapper around the hosts_access() routine with a
Xperhaps more convenient interface. hosts_ctl() returns zero if access
Xshould be denied.
X.SH DIAGNOSTICS
XProblems are reported via the syslog daemon.
X.SH SEE ALSO
Xhosts_access(5), format of the access control tables.
X.SH FILES
X/etc/hosts.access, /etc/hosts.deny, access control tables.
X.SH BUGS
XThe functions described here do not make copies of their string-valued
Xarguments. Beware of data from functions that overwrite their results
Xupon each call.
X.sp
Xhosts_access() uses the strtok() library function. This may interfere
Xwith other code that relies on strtok().
X.SH AUTHOR
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl)
XDepartment of Mathematics and Computing Science
XEindhoven University of Technology
XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X\" @(#) hosts_access.3 1.1 92/06/11 22:21:45
END_OF_hosts_access.3
if test 2018 -ne `wc -c <hosts_access.3`; then
echo shar: \"hosts_access.3\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_ctl.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"hosts_ctl.c\"
else
echo shar: Extracting \"hosts_ctl.c\" \(969 characters\)
sed "s/^X//" >hosts_ctl.c <<'END_OF_hosts_ctl.c'
X /*
X * hosts_ctl() combines the most common applications of the host access
X * control library. routine. It bundles its arguments into a from_host
X * structure, then calls the hosts_access() access control checker. The host
X * name and user name arguments should be empty strings, "unknown" or real
X * data. if a match is found, the optional shell command is executed.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_ctl.c 1.1 92/06/11 22:21:48";
X#endif
X
X#include <stdio.h>
X
X#include "log_tcp.h"
X
X/* hosts_ctl - general interface for the hosts_access() routine */
X
Xint hosts_ctl(daemon, name, addr, user)
Xchar *daemon;
Xchar *name;
Xchar *addr;
Xchar *user;
X{
X struct from_host client;
X static struct from_host zeros;
X
X client = zeros;
X client.name = name;
X client.addr = addr;
X client.user = user;
X
X return (hosts_access(daemon, &client));
X}
END_OF_hosts_ctl.c
if test 969 -ne `wc -c <hosts_ctl.c`; then
echo shar: \"hosts_ctl.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f percent_x.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"percent_x.c\"
else
echo shar: Extracting \"percent_x.c\" \(2603 characters\)
sed "s/^X//" >percent_x.c <<'END_OF_percent_x.c'
X /*
X * percent_x() takes a string and performs %a (host address), %c (client
X * info), %h (host name or address), %d (daemon name), %p (process id) and
X * %u (user name) substitutions. It aborts the program when the result of
X * expansion would overflow the output buffer. Because the result of %<char>
X * expansion is typically passed on to a shell process, characters that may
X * confuse the shell are replaced by underscores.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) percent_x.c 1.2 92/08/24 21:46:22";
X#endif
X
X/* System libraries. */
X
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strncpy();
Xextern char *strchr();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* percent_x - do %<char> expansion, abort if result buffer is too small */
X
Xvoid percent_x(result, result_len, str, daemon, client, pid)
Xchar *result;
Xint result_len;
Xchar *str;
Xchar *daemon;
Xstruct from_host *client;
Xint pid;
X{
X char *end = result + result_len - 1; /* end of result buffer */
X char *expansion;
X int expansion_len;
X char pid_buf[10];
X static char ok_chars[] = "1234567890!@%-_=+\\:,./\
Xabcdefghijklmnopqrstuvwxyz\
XABCDEFGHIJKLMNOPQRSTUVWXYZ";
X char *cp;
X
X /*
X * %a becomes the client address; %c all user and host information we
X * have about the client; %d the daemon process name; %h the client host
X * name or address; %p the daemon process id; %u the remote user name; %%
X * becomes a %, and %other is ignored. We terminate with a diagnostic if
X * we would overflow the result buffer. Characters that may confuse the
X * shell are mapped to underscores.
X */
X
X while (*str) {
X if (*str == '%') {
X str++;
X expansion =
X *str == 'a' ? (str++, client->addr) :
X *str == 'c' ? (str++, hosts_info(client)) :
X *str == 'd' ? (str++, daemon) :
X *str == 'h' ? (str++, FROM_HOST(client)) :
X *str == 'p' ? (str++, sprintf(pid_buf, "%d", pid), pid_buf) :
X *str == 'u' ? (str++, client->user) :
X *str == '%' ? (str++, "%") :
X *str == 0 ? "" : (str++, "");
X expansion_len = strlen(expansion);
X for (cp = expansion; *cp; cp++)
X if (strchr(ok_chars, *cp) == 0)
X *cp = '_';
X } else {
X expansion = str++;
X expansion_len = 1;
X }
X if (result + expansion_len >= end) {
X syslog(LOG_ERR, "shell command too long: %30s...", result);
X exit(0);
X }
X strncpy(result, expansion, expansion_len);
X result += expansion_len;
X }
X *result = 0;
X}
END_OF_percent_x.c
if test 2603 -ne `wc -c <percent_x.c`; then
echo shar: \"percent_x.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f options.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"options.c\"
else
echo shar: Extracting \"options.c\" \(10084 characters\)
sed "s/^X//" >options.c <<'END_OF_options.c'
X /*
X * General skeleton for adding options to the access control language. The
X * Makefile describes how this alternative language is enabled. Shell
X * commands will still be available, be it with a slightly different syntax.
X *
X * The code uses a slightly different format of access control rules. It
X * assumes that an access control rule looks like this:
X *
X * daemon_list : client_list : option : option ...
X *
X * An option is of the form "keyword" or "keyword = value". Option fields are
X * processed from left to right. Blanks around keywords, "=" and values are
X * optional. Blanks within values are left alone.
X *
X * Diagnostics are reported through syslog(3).
X *
X * Examples of options that are already implemented by the current skeleton:
X *
X * user = nobody
X *
X * Causes the process to switch its user id to that of "nobody". This normally
X * requires root privilege.
X *
X * group = tty
X *
X * Causes the process to change its group id to that of the "tty" group. In
X * order to switch both user and group ids you should normally switch the
X * group id before switching the user id.
X *
X * setenv = name value
X *
X * places a name,value pair into the environment. The value is subjected to
X * %<character> expansions.
X *
X * spawn = (/usr/ucb/finger -l @%h | /usr/ucb/mail root) &
X *
X * Executes (in a background child process) the shell command "finger -l @%h |
X * mail root" after doing the %<character> expansions described in the
X * hosts_access(5) manual page. The command is executed with stdin, stdout
X * and stderr connected to the null device. Because options are processed in
X * order, multiple spawn comands can be specified within the same access
X * control rule, though "spawn = command1; command2" would be more
X * efficient.
X *
X * in.ftpd : ... : twist = /bin/echo 421 Some customized bounce message
X *
X * Sends some custmized bounce message to the remote client instead of running
X * the real ftp daemon. The command is subjected to %<character> expansion
X * before execution by /bin/sh. Stdin, stdout and stderr are connected to the
X * remote client process. The twist'ed command overlays the current process;
X * it makes no sense to specify other options on the same line after a
X * "twist". The "twist" option was inspired by Dan Bernstein's shuctl daemon
X * wrapper control language.
X *
X * umask = value
X *
X * Sets the process file creation mask. Value must be an octal number.
X *
X * If you compile with -DRFC_OPTION, code is enabled for the following option
X * that does selective rfc931 lookups.
X *
X * rfc931
X *
X * Causes the daemon front ends to look up the remote user name with the RFC
X * 931 protocol.
X *
X * Warnings:
X *
X * This module uses the non-reentrant strtok() library routine. The options
X * argument to process_options() is destroyed.
X *
X * There cannot be a ":" character in keywords or values. Backslash sequences
X * are not yet recognized.
X *
X * In case of UDP connections, do not "twist" commands that use the standard
X * I/O or read(2)/write(2) routines to communicate with the client process;
X * UDP requires other communications primitives.
X *
X * In case of errors, use clean_exit() instead of directly calling exit(), or
X * your inetd may loop on an UDP request.
X */
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <sys/stat.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <pwd.h>
X#include <grp.h>
X#include <ctype.h>
X
Xextern char *strtok();
Xextern char *strchr();
Xextern void closelog();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* List of functions that implement the options. Add yours here. */
X
Xstatic void user_option(); /* execute "user=name" option */
Xstatic void group_option(); /* execute "group=name" option */
Xstatic void umask_option(); /* execute "umask=mask" option */
Xstatic void twist_option(); /* execute "twist=command" option */
X#ifdef RFC931_OPTION
Xstatic void rfc931_option(); /* execute "rfc931" option */
X#endif
Xstatic void setenv_option(); /* execute "setenv=name value" */
X
Xstatic char *chop_string(); /* strip leading and trailing blanks */
X
X/* Structure of the options table. */
X
Xstruct option {
X char *name; /* keyword name, case does not matter */
X int need_value; /* value required or not */
X void (*func) (); /* function that does the real work */
X};
X
X/* List of known keywords. Add yours here. */
X
Xstatic struct option option_table[] = {
X "user", 1, user_option, /* switch user id */
X "group", 1, group_option, /* switch group id */
X "umask", 1, umask_option, /* change umask */
X "spawn", 1, shell_cmd, /* spawn shell command */
X "twist", 1, twist_option, /* replace current process */
X#ifdef RFC931_OPTION
X "rfc931", 0, rfc931_option, /* do RFC 931 lookup */
X#endif
X "setenv", 1, setenv_option, /* update environment */
X 0,
X};
X
Xstatic char whitespace[] = " \t\r\n";
X
X/* process_options - process optional access control information */
X
Xprocess_options(options, daemon, client)
Xchar *options;
Xchar *daemon;
Xstruct from_host *client;
X{
X char *key;
X char *value;
X struct option *op;
X
X /*
X * Light-weight parser. Remember, we may be running as root so we need
X * code that is easy to comprehend.
X */
X
X for (key = strtok(options, ":"); key; key = strtok((char *) 0, ":")) {
X if (value = strchr(key, '=')) { /* keyword=value */
X *value++ = 0;
X value = chop_string(value); /* strip blanks around value */
X if (*value == 0)
X value = 0; /* no value left */
X }
X key = chop_string(key); /* strip blanks around key */
X for (op = option_table; op->name; op++) /* find keyword */
X if (strcasecmp(op->name, key) == 0)
X break;
X if (op->name == 0) {
X syslog(LOG_ERR, "bad option or syntax: \"%s\"", key);
X } else if (value == 0 && op->need_value) {
X syslog(LOG_ERR, "option \"%s\" requires value", key);
X } else if (value && op->need_value == 0) {
X syslog(LOG_ERR, "option \"%s\" requires no value", key);
X } else {
X (*(op->func)) (value, daemon, client);
X }
X }
X}
X
X/* user_option - switch user id */
X
X/* ARGSUSED */
X
Xstatic void user_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X struct passwd *pwd;
X struct passwd *getpwnam();
X
X if ((pwd = getpwnam(value)) == 0) {
X syslog(LOG_ERR, "unknown user: \"%s\"", value);
X clean_exit(client);
X } else if (setuid(pwd->pw_uid)) {
X syslog(LOG_ERR, "setuid(%s): %m", value);
X clean_exit(client);
X }
X}
X
X/* group_option - switch group id */
X
X/* ARGSUSED */
X
Xstatic void group_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X struct group *grp;
X struct group *getgrnam();
X
X if ((grp = getgrnam(value)) == 0) {
X syslog(LOG_ERR, "unknown group: \"%s\"", value);
X clean_exit(client);
X } else if (setgid(grp->gr_gid)) {
X syslog(LOG_ERR, "setgid(%s): %m", value);
X clean_exit(client);
X }
X}
X
X/* umask_option - set file creation mask */
X
X/* ARGSUSED */
X
Xstatic void umask_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X unsigned mask;
X char junk;
X
X if (sscanf(value, "%o%c", &mask, &junk) != 1 || (mask & 0777) != mask) {
X syslog(LOG_ERR, "bad umask: \"%s\"", value);
X clean_exit(client);
X }
X (void) umask(mask);
X}
X
X/* twist_option - replace process by shell command */
X
Xstatic void twist_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X char buf[BUFSIZ];
X int pid = getpid();
X char *error;
X
X percent_x(buf, sizeof(buf), value, daemon, client, pid);
X
X /* Since we will not be logging in the usual way, do it here and now. */
X
X syslog(SEVERITY, "twist from %s to %s", hosts_info(client), buf);
X closelog();
X
X /*
X * Before switching to the shell, set up stdout and stderr in case the
X * Ultrix inetd didn't.
X */
X
X (void) close(1);
X (void) close(2);
X if (dup(0) != 1 || dup(0) != 2) {
X error = "dup: %m";
X } else {
X (void) execl("/bin/sh", "sh", "-c", buf, (char *) 0);
X error = "/bin/sh: %m";
X }
X
X /* Can get here only in case of errors. */
X
X#ifdef LOG_MAIL
X (void) openlog(daemon, LOG_PID, FACILITY);
X#else
X (void) openlog(daemon, LOG_PID);
X#endif
X syslog(LOG_ERR, error);
X clean_exit(client);
X}
X
X#ifdef RFC931_OPTION
X
X/* rfc931_option - look up remote user name */
X
X/* ARGSUSED */
X
Xstatic void rfc931_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X if (client->sock_type == FROM_CONNECTED) {
X if (client->sin == 0) {
X syslog(LOG_ERR, "no socket info for username lookup");
X } else {
X client->user = rfc931_name(client->sin);
X }
X }
X}
X
X#endif
X
X/* setenv_option - set environment variable */
X
X/* ARGSUSED */
X
Xstatic void setenv_option(value, daemon, client)
Xchar *value;
Xchar *daemon;
Xstruct from_host *client;
X{
X char *var_name;
X char *var_value;
X char buf[BUFSIZ];
X int pid;
X
X /*
X * What we get is one string with the name and the value separated by
X * whitespace. Find the end of the name. If that is also the end of the
X * string, the value is empty.
X */
X
X var_value = value + strcspn(value, whitespace);
X
X if (*var_value == 0) { /* just a name, that's all */
X var_name = value;
X } else { /* expand %stuff in value */
X *var_value++ = 0;
X var_name = chop_string(value);
X pid = getpid();
X percent_x(buf, sizeof(buf), var_value, daemon, client, pid);
X var_value = chop_string(buf);
X }
X if (setenv(var_name, var_value, 1)) {
X syslog(LOG_ERR, "memory allocation failure");
X clean_exit(client);
X }
X}
X
X/* chop_string - strip leading and trailing blanks from string */
X
Xstatic char *chop_string(start)
Xregister char *start;
X{
X register char *end;
X
X while (*start && isspace(*start))
X start++;
X
X for (end = start + strlen(start); end > start && isspace(end[-1]); end--)
X /* void */ ;
X *end = 0;
X
X return (start);
X}
END_OF_options.c
if test 10084 -ne `wc -c <options.c`; then
echo shar: \"options.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f clean_exit.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"clean_exit.c\"
else
echo shar: Extracting \"clean_exit.c\" \(1268 characters\)
sed "s/^X//" >clean_exit.c <<'END_OF_clean_exit.c'
X /*
X * clean_exit() cleans up and terminates the program. It should be called
X * instead of exit when for some reason the real network daemon will not or
X * cannot be run. Reason: in the case of a datagram-oriented service we must
X * discard the not-yet received data from the client. Otherwise, inetd will
X * see the same datagram again and again, and go into a loop.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) clean_exit.c 1.1 92/06/11 22:21:52";
X#endif
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <stdio.h>
X
Xextern void exit();
X
X#include "log_tcp.h"
X
X/* clean_exit - clean up and exit */
X
Xvoid clean_exit(client)
Xstruct from_host *client;
X{
X char buf[BUFSIZ];
X struct sockaddr sa;
X int size = sizeof(sa);
X
X /*
X * Eat up the not-yet received packet. Some systems insist on a non-zero
X * source address argument in the recvfrom() call below.
X */
X
X if (client->sock_type == FROM_UNCONNECTED)
X (void) recvfrom(0, buf, sizeof(buf), 0, &sa, &size);
X
X /*
X * Be kind to the inetd. We already reported the problem via the syslogd,
X * and there is no need for additional garbage in the logfile.
X */
X
X exit(0);
X}
END_OF_clean_exit.c
if test 1268 -ne `wc -c <clean_exit.c`; then
echo shar: \"clean_exit.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f setenv.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"setenv.c\"
else
echo shar: Extracting \"setenv.c\" \(931 characters\)
sed "s/^X//" >setenv.c <<'END_OF_setenv.c'
X /*
X * Some systems do not have setenv(). This one is modeled after 4.4 BSD, but
X * is implemented in terms of portable primitives only: getenv(), putenv()
X * and malloc(). It should therefore be safe to use on every UNIX system.
X *
X * If clobber == 0, do not overwrite an existing variable.
X *
X * Returns nonzero if memory allocation fails.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) setenv.c 1.1 93/03/07 22:47:58";
X#endif
X
X/* setenv - update or insert environment (name,value) pair */
X
Xint setenv(name, value, clobber)
Xchar *name;
Xchar *value;
Xint clobber;
X{
X char *malloc();
X char *getenv();
X char *cp;
X
X if (clobber == 0 && getenv(name) != 0)
X return (0);
X if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0)
X return (1);
X sprintf(cp, "%s=%s", name, value);
X return (putenv(cp));
X}
END_OF_setenv.c
if test 931 -ne `wc -c <setenv.c`; then
echo shar: \"setenv.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f patchlevel.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"patchlevel.h\"
else
echo shar: Extracting \"patchlevel.h\" \(70 characters\)
sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
X#ifndef lint
Xstatic char patchlevel[] = "@(#) patchlevel 5.1";
X#endif
END_OF_patchlevel.h
if test 70 -ne `wc -c <patchlevel.h`; then
echo shar: \"patchlevel.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f strtok.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"strtok.c\"
else
echo shar: Extracting \"strtok.c\" \(2976 characters\)
sed "s/^X//" >strtok.c <<'END_OF_strtok.c'
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by the University of
X * California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X * may be used to endorse or promote products derived from this software
X * without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strtok.c 5.8 (Berkeley) 2/24/91";
X#endif /* LIBC_SCCS and not lint */
X
X#ifdef __STDC__ /* Added for backwards compatibility -- WZV 930122 */
X#include <stddef.h>
X#include <string.h>
X#else
X#define const
X#define NULL 0
X#endif
X
Xchar *
Xstrtok(s, delim)
X register char *s;
X register const char *delim;
X{
X register char *spanp;
X register int c, sc;
X char *tok;
X static char *last;
X
X
X if (s == NULL && (s = last) == NULL)
X return (NULL);
X
X /*
X * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
X */
Xcont:
X c = *s++;
X for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
X if (c == sc)
X goto cont;
X }
X
X if (c == 0) { /* no non-delimiter characters */
X last = NULL;
X return (NULL);
X }
X tok = s - 1;
X
X /*
X * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
X * Note that delim must have one NUL; we stop if we see that, too.
X */
X for (;;) {
X c = *s++;
X spanp = (char *)delim;
X do {
X if ((sc = *spanp++) == c) {
X if (c == 0)
X s = NULL;
X else
X s[-1] = 0;
X last = s;
X return (tok);
X }
X } while (sc != 0);
X }
X /* NOTREACHED */
X}
END_OF_strtok.c
if test 2976 -ne `wc -c <strtok.c`; then
echo shar: \"strtok.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fix_options.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"fix_options.c\"
else
echo shar: Extracting \"fix_options.c\" \(1315 characters\)
sed "s/^X//" >fix_options.c <<'END_OF_fix_options.c'
X /*
X * Routine to disable IP-level socket options. This code was taken from 4.4BSD
X * rlogind source, but all mistakes in it are my fault.
X *
X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) fix_options.c 1.1 93/03/07 22:48:02";
X#endif
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X
X#include "log_tcp.h"
X
X/* fix_options - get rid of IP-level socket options */
X
Xfix_options(client)
Xstruct from_host *client;
X{
X#ifdef IP_OPTIONS
X unsigned char optbuf[BUFSIZ / 3], *cp;
X char lbuf[BUFSIZ], *lp;
X int optsize = sizeof(optbuf), ipproto;
X struct protoent *ip;
X
X if ((ip = getprotobyname("ip")) != 0)
X ipproto = ip->p_proto;
X else
X ipproto = IPPROTO_IP;
X
X if (getsockopt(0, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0
X && optsize != 0) {
X lp = lbuf;
X for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
X sprintf(lp, " %2.2x", *cp);
X syslog(LOG_NOTICE,
X "connect from %s with IP options (ignored):%s",
X hosts_info(client), lbuf);
X if (setsockopt(0, ipproto, IP_OPTIONS, (char *) 0, optsize) != 0) {
X syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
X clean_exit(client);
X }
X }
X#endif
X}
END_OF_fix_options.c
if test 1315 -ne `wc -c <fix_options.c`; then
echo shar: \"fix_options.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f inet_addr_fix -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"inet_addr_fix\"
else
echo shar: Extracting \"inet_addr_fix\" \(552 characters\)
sed "s/^X//" >inet_addr_fix <<'END_OF_inet_addr_fix'
X#ifndef lint
Xstatic char sccsid[] = "@(#) inet_addr_fix 1.1 93/03/07 22:48:04";
X#endif
X
X /*
X * Some inet_addr() versions return a struct/union instead of a long. You
X * have this problem when the compiler complains about illegal lvalues or
X * something like that. The following code fixes this mutant behaviour.
X *
X * Bug reported by ben@piglet.cr.usgs.gov (Rev. Ben A. Mesander).
X */
X
Xstatic long fix_inet_addr(string)
Xchar *string;
X{
X struct in_addr addr = inet_addr(string);
X
X return (addr.s_addr);
X}
X
X#define inet_addr fix_inet_addr
END_OF_inet_addr_fix
if test 552 -ne `wc -c <inet_addr_fix`; then
echo shar: \"inet_addr_fix\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0